From d1cf88eb601175a0f0ff7fb6125f7417422098a1 Mon Sep 17 00:00:00 2001 From: James Eastham Date: Tue, 1 Jul 2025 15:56:57 +0100 Subject: [PATCH 1/6] feat: improvements to .NET code sample * chore: improve error handling * chore: update logging and add validation * feat: add versioning, rate limiting and health checks * fix: resolve integration test issues with paged response * fix: update frontend to support paged order responses * Update src/order-service/src/Orders.Api/Program.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Potential fix for code scanning alert no. 178: Log entries created from user input Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- src/frontend/src/admin/orders/page.js | 4 +- src/order-service/CLAUDE.md | 3397 +++++++++++++++++ .../CompleteOrder/CompleteOrderHandler.cs | 102 +- .../CompleteOrder/CompleteOrderRequest.cs | 15 - .../ConfirmedOrders/ConfirmedOrdersHandler.cs | 92 +- .../CreateOrder/CreateOrderHandler.cs | 129 +- .../GetOrderDetails/GetOrderDetailsHandler.cs | 80 +- .../GetUserOrders/GetUserOrdersHandler.cs | 120 +- .../Health/ApplicationHealthCheck.cs | 151 + .../Orders.Api/Health/DynamoDbHealthCheck.cs | 94 + .../Orders.Api/Health/MemoryHealthCheck.cs | 120 + .../Logging/LoggerMessageDefinitions.cs | 307 ++ .../Orders.Api/Logging/StructuredLogging.cs | 333 ++ .../Middleware/CorrelationIdMiddleware.cs | 33 + .../GlobalExceptionHandlingMiddleware.cs | 73 +- .../Middleware/MiddlewareExtensions.cs | 8 + .../Orders.Api/Models/CompleteOrderRequest.cs | 48 + .../Orders.Api/Models/CreateOrderRequest.cs | 18 +- .../src/Orders.Api/Models/ErrorResponse.cs | 37 + .../Models/RouteParameterValidators.cs | 102 + .../src/Orders.Api/Orders.Api.csproj | 1 + src/order-service/src/Orders.Api/Program.cs | 246 +- .../RateLimiting/RateLimitPolicies.cs | 36 + .../RateLimiting/RateLimitingMetrics.cs | 81 + .../src/Orders.Api/TraceExtensions.cs | 3 +- .../src/Orders.Api/V1/Models/OrderDtoV1.cs | 75 + .../Versioning/ApiDeprecationMiddleware.cs | 103 + .../Orders.Core/Adapters/DynamoDBOrders.cs | 144 +- .../Orders.Core/Common/PaginationModels.cs | 52 + .../src/Orders.Core/Common/Result.cs | 85 + .../Exceptions/OrderNotFoundException.cs | 30 + .../Exceptions/OrderValidationException.cs | 28 + .../Domain/Exceptions/WorkflowException.cs | 25 + src/order-service/src/Orders.Core/IOrders.cs | 45 +- .../ApiIntegrationTests.cs | 27 +- .../PagedResponse.cs} | 12 +- .../Api/ErrorHandlingTests.cs | 143 + .../Orders.UnitTests/Orders.UnitTests.csproj | 1 + 38 files changed, 6251 insertions(+), 149 deletions(-) create mode 100644 src/order-service/CLAUDE.md delete mode 100644 src/order-service/src/Orders.Api/CompleteOrder/CompleteOrderRequest.cs create mode 100644 src/order-service/src/Orders.Api/Health/ApplicationHealthCheck.cs create mode 100644 src/order-service/src/Orders.Api/Health/DynamoDbHealthCheck.cs create mode 100644 src/order-service/src/Orders.Api/Health/MemoryHealthCheck.cs create mode 100644 src/order-service/src/Orders.Api/Logging/LoggerMessageDefinitions.cs create mode 100644 src/order-service/src/Orders.Api/Logging/StructuredLogging.cs create mode 100644 src/order-service/src/Orders.Api/Middleware/CorrelationIdMiddleware.cs create mode 100644 src/order-service/src/Orders.Api/Models/CompleteOrderRequest.cs create mode 100644 src/order-service/src/Orders.Api/Models/ErrorResponse.cs create mode 100644 src/order-service/src/Orders.Api/Models/RouteParameterValidators.cs create mode 100644 src/order-service/src/Orders.Api/RateLimiting/RateLimitPolicies.cs create mode 100644 src/order-service/src/Orders.Api/RateLimiting/RateLimitingMetrics.cs create mode 100644 src/order-service/src/Orders.Api/V1/Models/OrderDtoV1.cs create mode 100644 src/order-service/src/Orders.Api/Versioning/ApiDeprecationMiddleware.cs create mode 100644 src/order-service/src/Orders.Core/Common/PaginationModels.cs create mode 100644 src/order-service/src/Orders.Core/Common/Result.cs create mode 100644 src/order-service/src/Orders.Core/Domain/Exceptions/OrderNotFoundException.cs create mode 100644 src/order-service/src/Orders.Core/Domain/Exceptions/OrderValidationException.cs create mode 100644 src/order-service/src/Orders.Core/Domain/Exceptions/WorkflowException.cs rename src/order-service/src/{Orders.Api/CreateOrder/CreateOrderRequest.cs => Orders.IntegrationTests/PagedResponse.cs} (50%) create mode 100644 src/order-service/src/Orders.UnitTests/Api/ErrorHandlingTests.cs diff --git a/src/frontend/src/admin/orders/page.js b/src/frontend/src/admin/orders/page.js index 3aa4c3da..5ad72cec 100644 --- a/src/frontend/src/admin/orders/page.js +++ b/src/frontend/src/admin/orders/page.js @@ -48,7 +48,7 @@ function refreshData() { contentType: "application/json", success: function (response) { loadingSpinner.ariaBusy = false; - response.forEach((message) => { + response.items.forEach((message) => { console.log(message); var rowElement = document.createElement("tr"); @@ -75,7 +75,7 @@ function refreshData() { }, beforeSend: function (xhr) { xhr.setRequestHeader("Authorization", `Bearer ${jwt}`); - } + }, }); } diff --git a/src/order-service/CLAUDE.md b/src/order-service/CLAUDE.md new file mode 100644 index 00000000..fb6d459c --- /dev/null +++ b/src/order-service/CLAUDE.md @@ -0,0 +1,3397 @@ +# Development Guidelines for .NET + +The order services allows users to place orders, and traces the flow of an order through the system using a Step Function workflow. It is made up of 2 independent services + +1. The `Orders.Api` provides various API endpoints to create, update and manage orders as they flow through the system +2. The `Orders.BackgroundWorkers` service is an [anti-corruption layer](https://learn.microsoft.com/en-us/azure/architecture/patterns/anti-corruption-layer) that consumes events published by external services, translates them to internal events and processes them + +The .NET sample code uses the [Lambda Annotations Framework](https://github.com/aws/aws-lambda-dotnet/blob/master/Libraries/src/Amazon.Lambda.Annotations/README.md) to simplify how you define Lambda functions. + +## Core Philosophy + +**TEST-DRIVEN DEVELOPMENT IS NON-NEGOTIABLE.** Every single line of production code must be written in response to a failing test. No exceptions. This is not a suggestion or a preference - it is the fundamental practice that enables all other principles in this document. + +I follow Test-Driven Development (TDD) with a strong emphasis on behavior-driven testing and functional programming principles. All work should be done in small, incremental changes that maintain a working state throughout development. + +## Quick Reference + +**Key Principles:** + +- Write tests first (TDD) +- Test behavior, not implementation +- Nullable reference types enabled +- Immutable data only +- Small, pure functions +- C# 12+ features and .NET 9 +- Use real models/DTOs in tests, never redefine them + +**Preferred Tools:** + +- **Language**: C# 12+ (.NET 9) +- **Testing**: xUnit + FluentAssertions no higher than version 7 + Testcontainers +- **State Management**: Prefer immutable patterns and records +- **Validation**: FluentValidation +- **Serialization**: System.Text.Json + +## AWS Serverless Best Practices + +### Lambda Function Development + +#### Lambda Annotations Framework + +Use the [Lambda Annotations Framework](https://github.com/aws/aws-lambda-dotnet/tree/master/Libraries/src/Amazon.Lambda.Annotations) for simplified Lambda function development: + +```csharp +[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))] + +namespace PaymentProcessor.Lambda; + +public class PaymentApiFunction +{ + private readonly IPaymentService _paymentService; + + public PaymentApiFunction(IPaymentService paymentService) + { + _paymentService = paymentService; + } + + [LambdaFunction] + [HttpApi(LambdaHttpMethod.Post, "/payments")] + public async Task ProcessPayment([FromBody] PaymentRequest request) + { + var result = await _paymentService.ProcessPaymentAsync(request); + + return result.IsSuccess + ? HttpResults.Ok(result.Value) + : HttpResults.BadRequest(result.Error); + } +} +``` + +### Dependency Injection and Options Pattern + +Use the `[LambdaStartup]` attribute to configure dependency injection and use the options pattern: + +```csharp + + +```csharp +// Configuration +public class PaymentOptions +{ + public const string SectionName = "Payment"; + + public decimal MaxAmount { get; set; } = 10000m; + public string[] AcceptedCurrencies { get; set; } = Array.Empty(); + public string ApiKey { get; set; } = string.Empty; + public string BaseUrl { get; set; } = string.Empty; +} + +// Service registration +[LambdaStartup] +public class Startup +{ + public void ConfigureServices(IServiceCollection services) + { + services.Configure( + configuration.GetSection(PaymentOptions.SectionName)); + + services.AddScoped(); + services.AddScoped(); + services.AddScoped, PaymentRequestValidator>(); + + services.AddHttpClient((serviceProvider, client) => + { + var options = serviceProvider.GetRequiredService>().Value; + client.BaseAddress = new Uri(options.BaseUrl); + client.DefaultRequestHeaders.Add("X-API-Key", options.ApiKey); + }); + + return services; + } +} + +// Service implementation +public class PaymentService : IPaymentService +{ + private readonly IPaymentRepository _paymentRepository; + private readonly IValidator _validator; + private readonly ILogger _logger; + private readonly PaymentOptions _options; + + public PaymentService( + IPaymentRepository paymentRepository, + IValidator validator, + ILogger logger, + IOptions options) + { + _paymentRepository = paymentRepository ?? throw new ArgumentNullException(nameof(paymentRepository)); + _validator = validator ?? throw new ArgumentNullException(nameof(validator)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _options = options?.Value ?? throw new ArgumentNullException(nameof(options)); + } + + public async Task> ProcessPaymentAsync( + PaymentRequest request, + CancellationToken cancellationToken = default) + { + var validationResult = await _validator.ValidateAsync(request, cancellationToken); + if (!validationResult.IsValid) + { + var errors = string.Join(", ", validationResult.Errors.Select(e => e.ErrorMessage)); + return ResultExtensions.Failure($"Validation failed: {errors}"); + } + + if (request.Amount > _options.MaxAmount) + { + return ResultExtensions.Failure($"Amount exceeds maximum allowed: {_options.MaxAmount}"); + } + + // Process payment... + return ResultExtensions.Success(new Payment(PaymentId.New(), request.Amount, request.Currency)); + } +} +``` + +## Testing Principles + +### Behavior-Driven Testing + +- **No "unit tests"** - this term is not helpful. Tests should verify expected behavior, treating implementation as a black box +- Test through the public API exclusively - internals should be invisible to tests +- Create tests in a separate project directory underneath the `tests` directory +- Tests that examine internal implementation details are wasteful and should be avoided +- Tests must document expected business behaviour + +### Testing Tools + +- **xUnit** for testing framework +- **FluentAssertions** for readable assertions +- **Testcontainers** for integration testing with real dependencies +- **Microsoft.AspNetCore.Mvc.Testing** for API testing +- **Moq** for mocking when absolutely necessary (prefer real implementations) +- All test code must follow the same C# standards as production code + +### Test Organization + +``` +src/ + PaymentProcessorApplication/ + PaymentProcessorApplication.csproj + PaymentProcessor.cs + PaymentValidator.cs +tests/ + PaymentProcessorApplication.Tests/ + PaymentProcessor.Tests.cs // The validator is an implementation detail. Validation is fully covered, but by testing the expected business behaviour +``` + +### Test Data Pattern + +Use builder pattern with fluent interfaces for test data: + +```csharp +public class PaymentRequestBuilder +{ + private decimal _amount = 100m; + private string _currency = "GBP"; + private string _cardId = "card_123"; + private string _customerId = "cust_456"; + private string? _description; + private Dictionary? _metadata; + private string? _idempotencyKey; + private AddressDetails _addressDetails = new AddressDetailsBuilder().Build(); + private PayingCardDetails _payingCardDetails = new PayingCardDetailsBuilder().Build(); + + public PaymentRequestBuilder WithAmount(decimal amount) + { + _amount = amount; + return this; + } + + public PaymentRequestBuilder WithCurrency(string currency) + { + _currency = currency; + return this; + } + + public PaymentRequestBuilder WithCardId(string cardId) + { + _cardId = cardId; + return this; + } + + public PaymentRequestBuilder WithCustomerId(string customerId) + { + _customerId = customerId; + return this; + } + + public PaymentRequestBuilder WithDescription(string description) + { + _description = description; + return this; + } + + public PaymentRequestBuilder WithMetadata(Dictionary metadata) + { + _metadata = metadata; + return this; + } + + public PaymentRequestBuilder WithIdempotencyKey(string idempotencyKey) + { + _idempotencyKey = idempotencyKey; + return this; + } + + public PaymentRequestBuilder WithAddressDetails(AddressDetails addressDetails) + { + _addressDetails = addressDetails; + return this; + } + + public PaymentRequestBuilder WithPayingCardDetails(PayingCardDetails payingCardDetails) + { + _payingCardDetails = payingCardDetails; + return this; + } + + public PaymentRequest Build() + { + return new PaymentRequest( + _amount, + _currency, + _cardId, + _customerId, + _description, + _metadata, + _idempotencyKey, + _addressDetails, + _payingCardDetails + ); + } +} + +public class AddressDetailsBuilder +{ + private string _houseNumber = "123"; + private string? _houseName = "Test House"; + private string _addressLine1 = "Test Address Line 1"; + private string? _addressLine2 = "Test Address Line 2"; + private string _city = "Test City"; + private string _postcode = "SW1A 1AA"; + + public AddressDetailsBuilder WithHouseNumber(string houseNumber) + { + _houseNumber = houseNumber; + return this; + } + + public AddressDetailsBuilder WithHouseName(string? houseName) + { + _houseName = houseName; + return this; + } + + public AddressDetailsBuilder WithAddressLine1(string addressLine1) + { + _addressLine1 = addressLine1; + return this; + } + + public AddressDetailsBuilder WithAddressLine2(string? addressLine2) + { + _addressLine2 = addressLine2; + return this; + } + + public AddressDetailsBuilder WithCity(string city) + { + _city = city; + return this; + } + + public AddressDetailsBuilder WithPostcode(string postcode) + { + _postcode = postcode; + return this; + } + + public AddressDetails Build() + { + return new AddressDetails( + _houseNumber, + _houseName, + _addressLine1, + _addressLine2, + _city, + _postcode + ); + } +} + +// Usage in tests +var paymentRequest = new PaymentRequestBuilder() + .WithAmount(250m) + .WithCurrency("USD") + .WithMetadata(new Dictionary { ["orderId"] = "order_789" }) + .WithAddressDetails(new AddressDetailsBuilder() + .WithCity("London") + .WithPostcode("E1 6AN") + .Build()) + .Build(); +``` + +Key principles: + +- Always return complete objects with sensible defaults +- Use fluent interfaces for readable test setup +- Build incrementally - extract nested object builders as needed +- Compose builders for complex objects +- Make builders immutable by returning new instances + +## C# and .NET Guidelines + +### Project Structure + +### Project Structure + +``` +src/ + YourApp.Api/ # Web API project + YourApp.Core/ # Application layer (use cases, services), Domain models, entities, value objects, DTOs, requests, responses + YourApp.Adapters/ # Data access, external services + YourApp.BackgroundWorkers/ # This project is only required if the service performs asynchronous work. It is seperate to run any background workers independently from a synchronous API +tests/ + YourApp.Api.Tests/ # API integration tests + YourApp.Application.Tests/ # Core layer tests +``` + +Inside the .Core library, DO NOT create folders based on technical feature (Entities, DTO's, Services). Instead, create folders based on the actual business value that grouped set of code performs. Loosely following a vertical slice architecture style. A new developer should be able to look at the files/folders inside a project and understand what is is that the application does. + +### C# Language Features + +#### Records and Immutability + +Use records for data transfer objects and value objects: + +```csharp +// Good - Immutable record +public record PaymentRequest( + decimal Amount, + string Currency, + string CardId, + string CustomerId, + string? Description = null, + Dictionary? Metadata = null, + string? IdempotencyKey = null, + AddressDetails AddressDetails, + PayingCardDetails PayingCardDetails +); + +public record AddressDetails( + string HouseNumber, + string? HouseName, + string AddressLine1, + string? AddressLine2, + string City, + string Postcode +); + +// For domain entities with behavior +public class Payment +{ + public PaymentId Id { get; } + public decimal Amount { get; } + public string Currency { get; } + public PaymentStatus Status { get; private set; } + public DateTime CreatedAt { get; } + public DateTime? ProcessedAt { get; private set; } + + public Payment(PaymentId id, decimal amount, string currency) + { + Id = id; + Amount = amount; + Currency = currency; + Status = PaymentStatus.Pending; + CreatedAt = DateTime.UtcNow; + } + + public void MarkAsProcessed() + { + if (Status != PaymentStatus.Pending) + { + throw new InvalidOperationException("Payment can only be processed when pending"); + } + + Status = PaymentStatus.Processed; + ProcessedAt = DateTime.UtcNow; + } +} +``` + +#### Nullable Reference Types + +Always enable nullable reference types: + +```xml + + + enable + true + + +``` + +```csharp +// Good - Explicit nullability +public class PaymentService +{ + private readonly IPaymentRepository _paymentRepository; + private readonly ILogger _logger; + + public PaymentService( + IPaymentRepository paymentRepository, + ILogger logger) + { + _paymentRepository = paymentRepository ?? throw new ArgumentNullException(nameof(paymentRepository)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } + + public async Task GetPaymentAsync(PaymentId id, CancellationToken cancellationToken = default) + { + return await _paymentRepository.GetByIdAsync(id, cancellationToken); + } + + public async Task CreatePaymentAsync(PaymentRequest request, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(request); + + var payment = new Payment(PaymentId.New(), request.Amount, request.Currency); + await _paymentRepository.AddAsync(payment, cancellationToken); + + return payment; + } +} +``` + +#### Result Pattern + +Use Result pattern for error handling: + +```csharp +public abstract record Result +{ + public abstract bool IsSuccess { get; } + public abstract bool IsFailure => !IsSuccess; +} + +public sealed record Success(T Value) : Result +{ + public override bool IsSuccess => true; +} + +public sealed record Failure(string Error, Exception? Exception = null) : Result +{ + public override bool IsSuccess => false; +} + +// Extension methods for fluent usage +public static class ResultExtensions +{ + public static Result Success(T value) => new Success(value); + public static Result Failure(string error, Exception? exception = null) => new Failure(error, exception); + + public static Result Map(this Result result, Func mapper) + { + return result switch + { + Success success => Success(mapper(success.Value)), + Failure failure => Failure(failure.Error, failure.Exception), + _ => throw new InvalidOperationException("Unknown result type") + }; + } + + public static async Task> MapAsync( + this Result result, + Func> mapper) + { + return result switch + { + Success success => Success(await mapper(success.Value)), + Failure failure => Failure(failure.Error, failure.Exception), + _ => throw new InvalidOperationException("Unknown result type") + }; + } + + public static Result FlatMap(this Result result, Func> mapper) + { + return result switch + { + Success success => mapper(success.Value), + Failure failure => Failure(failure.Error, failure.Exception), + _ => throw new InvalidOperationException("Unknown result type") + }; + } +} + +// Usage +public async Task> ProcessPaymentAsync(PaymentRequest request, CancellationToken cancellationToken = default) +{ + var validationResult = await ValidatePaymentRequestAsync(request, cancellationToken); + if (validationResult.IsFailure) + { + return ResultExtensions.Failure(validationResult.Error); + } + + var authorizationResult = await AuthorizePaymentAsync(request, cancellationToken); + if (authorizationResult.IsFailure) + { + return ResultExtensions.Failure(authorizationResult.Error); + } + + var payment = new Payment(PaymentId.New(), request.Amount, request.Currency); + await _paymentRepository.AddAsync(payment, cancellationToken); + + return ResultExtensions.Success(payment); +} +``` + +#### Strongly Typed IDs + +Use strongly typed IDs to prevent primitive obsession: + +```csharp +public readonly record struct PaymentId(Guid Value) +{ + public static PaymentId New() => new(Guid.NewGuid()); + public static PaymentId Parse(string value) => new(Guid.Parse(value)); + public override string ToString() => Value.ToString(); +} + +public readonly record struct CustomerId(Guid Value) +{ + public static CustomerId New() => new(Guid.NewGuid()); + public static CustomerId Parse(string value) => new(Guid.Parse(value)); + public override string ToString() => Value.ToString(); +} + +// Usage prevents mixing up IDs +public async Task GetPaymentAsync(PaymentId paymentId, CancellationToken cancellationToken = default) +{ + // Compiler prevents passing CustomerId here + return await _paymentRepository.GetByIdAsync(paymentId, cancellationToken); +} +``` + +### Validation with FluentValidation + +```csharp +public class PaymentRequestValidator : AbstractValidator +{ + public PaymentRequestValidator() + { + RuleFor(x => x.Amount) + .GreaterThan(0) + .WithMessage("Amount must be greater than zero") + .LessThanOrEqualTo(10000) + .WithMessage("Amount cannot exceed £10,000"); + + RuleFor(x => x.Currency) + .NotEmpty() + .Must(BeValidCurrency) + .WithMessage("Currency must be a valid ISO currency code"); + + RuleFor(x => x.CardId) + .NotEmpty() + .Length(16) + .WithMessage("Card ID must be 16 characters"); + + RuleFor(x => x.AddressDetails) + .NotNull() + .SetValidator(new AddressDetailsValidator()); + + RuleFor(x => x.PayingCardDetails) + .NotNull() + .SetValidator(new PayingCardDetailsValidator()); + } + + private static bool BeValidCurrency(string currency) + { + var validCurrencies = new[] { "GBP", "USD", "EUR" }; + return validCurrencies.Contains(currency); + } +} + +public class AddressDetailsValidator : AbstractValidator +{ + public AddressDetailsValidator() + { + RuleFor(x => x.HouseNumber) + .NotEmpty() + .WithMessage("House number is required"); + + RuleFor(x => x.AddressLine1) + .NotEmpty() + .WithMessage("Address line 1 is required"); + + RuleFor(x => x.City) + .NotEmpty() + .WithMessage("City is required"); + + RuleFor(x => x.Postcode) + .NotEmpty() + .Matches(@"^[A-Z]{1,2}\d[A-Z\d]? ?\d[A-Z]{2}$") + .WithMessage("Postcode must be a valid UK postcode"); + } +} +``` + +#### Model Validation in Tests + +**CRITICAL**: Tests must use real validators and models from the main project, not redefine their own. + +```csharp +// ❌ WRONG - Defining validators in test files +public class TestPaymentRequestValidator : AbstractValidator +{ + public TestPaymentRequestValidator() + { + RuleFor(x => x.Amount).GreaterThan(0); + // ... other rules + } +} + +// ✅ CORRECT - Import validators from the main project +using YourApp.Application.Validators; + +[Fact] +public async Task ProcessPayment_ShouldFailValidation_WhenAmountIsNegative() +{ + // Arrange + var paymentRequest = new PaymentRequestBuilder() + .WithAmount(-100m) + .Build(); + + var validator = new PaymentRequestValidator(); + var paymentService = new PaymentService(_paymentRepository, validator, _logger); + + // Act + var result = await paymentService.ProcessPaymentAsync(paymentRequest); + + // Assert + result.IsFailure.Should().BeTrue(); + result.Should().BeOfType>(); + var failure = (Failure)result; + failure.Error.Should().Contain("Amount must be greater than zero"); +} +``` + +## Code Style + +### Code Structure + +- **No nested if/else statements** - use early returns, guard clauses, or pattern matching +- **Avoid deep nesting** in general (max 2 levels) +- Keep methods small and focused on a single responsibility +- Prefer flat, readable code over clever abstractions + +### Naming Conventions + +- **Methods**: `PascalCase`, verb-based (e.g., `CalculateTotal`, `ValidatePayment`) +- **Properties**: `PascalCase` (e.g., `PaymentAmount`, `CustomerDetails`) +- **Fields**: `_camelCase` for private fields +- **Constants**: `PascalCase` for public constants, `_camelCase` for private constants +- **Types**: `PascalCase` (e.g., `PaymentRequest`, `UserProfile`) +- **Files**: `PascalCase.cs` for all C# files +- **Test files**: `*.Tests.cs` + +### No Comments in Code + +Code should be self-documenting through clear naming and structure. Comments indicate that the code itself is not clear enough. + +```csharp +// Avoid: Comments explaining what the code does +public static decimal CalculateDiscount(decimal price, Customer customer) +{ + // Check if customer is premium + if (customer.Tier == CustomerTier.Premium) + { + // Apply 20% discount for premium customers + return price * 0.8m; + } + // Regular customers get 10% discount + return price * 0.9m; +} + +// Good: Self-documenting code with clear names +private const decimal PremiumDiscountMultiplier = 0.8m; +private const decimal StandardDiscountMultiplier = 0.9m; + +private static bool IsPremiumCustomer(Customer customer) +{ + return customer.Tier == CustomerTier.Premium; +} + +public static decimal CalculateDiscount(decimal price, Customer customer) +{ + var discountMultiplier = IsPremiumCustomer(customer) + ? PremiumDiscountMultiplier + : StandardDiscountMultiplier; + + return price * discountMultiplier; +} +``` + +**Exception**: XML documentation comments for public APIs are acceptable when generating documentation, but the code should still be self-explanatory without them. + +### Dependency Injection and Options Pattern + +Use the built-in DI container and options pattern: + +```csharp +// Configuration +public class PaymentOptions +{ + public const string SectionName = "Payment"; + + public decimal MaxAmount { get; set; } = 10000m; + public string[] AcceptedCurrencies { get; set; } = Array.Empty(); + public string ApiKey { get; set; } = string.Empty; + public string BaseUrl { get; set; } = string.Empty; +} + +// Service registration +public static class ServiceCollectionExtensions +{ + public static IServiceCollection AddPaymentServices( + this IServiceCollection services, + IConfiguration configuration) + { + services.Configure( + configuration.GetSection(PaymentOptions.SectionName)); + + services.AddScoped(); + services.AddScoped(); + services.AddScoped, PaymentRequestValidator>(); + + services.AddHttpClient((serviceProvider, client) => + { + var options = serviceProvider.GetRequiredService>().Value; + client.BaseAddress = new Uri(options.BaseUrl); + client.DefaultRequestHeaders.Add("X-API-Key", options.ApiKey); + }); + + return services; + } +} + +// Service implementation +public class PaymentService : IPaymentService +{ + private readonly IPaymentRepository _paymentRepository; + private readonly IValidator _validator; + private readonly ILogger _logger; + private readonly PaymentOptions _options; + + public PaymentService( + IPaymentRepository paymentRepository, + IValidator validator, + ILogger logger, + IOptions options) + { + _paymentRepository = paymentRepository ?? throw new ArgumentNullException(nameof(paymentRepository)); + _validator = validator ?? throw new ArgumentNullException(nameof(validator)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _options = options?.Value ?? throw new ArgumentNullException(nameof(options)); + } + + public async Task> ProcessPaymentAsync( + PaymentRequest request, + CancellationToken cancellationToken = default) + { + var validationResult = await _validator.ValidateAsync(request, cancellationToken); + if (!validationResult.IsValid) + { + var errors = string.Join(", ", validationResult.Errors.Select(e => e.ErrorMessage)); + return ResultExtensions.Failure($"Validation failed: {errors}"); + } + + if (request.Amount > _options.MaxAmount) + { + return ResultExtensions.Failure($"Amount exceeds maximum allowed: {_options.MaxAmount}"); + } + + // Process payment... + return ResultExtensions.Success(new Payment(PaymentId.New(), request.Amount, request.Currency)); + } +} +``` + +## Development Workflow + +### TDD Process - THE FUNDAMENTAL PRACTICE + +**CRITICAL**: TDD is not optional. Every feature, every bug fix, every change MUST follow this process: + +Follow Red-Green-Refactor strictly: + +1. **Red**: Write a failing test for the desired behavior. NO PRODUCTION CODE until you have a failing test. +2. **Green**: Write the MINIMUM code to make the test pass. Resist the urge to write more than needed. +3. **Refactor**: Assess the code for improvement opportunities. If refactoring would add value, clean up the code while keeping tests green. If the code is already clean and expressive, move on. + +#### TDD Example Workflow + +```csharp +// Step 1: Red - Start with the simplest behavior +[Fact] +public void ProcessOrder_ShouldCalculateTotal_WithShippingCost() +{ + // Arrange + var order = new OrderBuilder() + .WithItems(new OrderItem(30m, 1)) + .WithShippingCost(5.99m) + .Build(); + + // Act + var processed = ProcessOrder(order); + + // Assert + processed.Total.Should().Be(35.99m); + processed.ShippingCost.Should().Be(5.99m); +} + +// Step 2: Green - Minimal implementation +public static ProcessedOrder ProcessOrder(Order order) +{ + var itemsTotal = order.Items.Sum(item => item.Price * item.Quantity); + + return new ProcessedOrder + { + Items = order.Items, + ShippingCost = order.ShippingCost, + Total = itemsTotal + order.ShippingCost + }; +} + +// Step 3: Red - Add test for free shipping behavior +[Fact] +public void ProcessOrder_ShouldApplyFreeShipping_ForOrdersOver50() +{ + // Arrange + var order = new OrderBuilder() + .WithItems(new OrderItem(60m, 1)) + .WithShippingCost(5.99m) + .Build(); + + // Act + var processed = ProcessOrder(order); + + // Assert + processed.ShippingCost.Should().Be(0m); + processed.Total.Should().Be(60m); +} + +// Step 4: Green - NOW we can add the conditional because both paths are tested +public static ProcessedOrder ProcessOrder(Order order) +{ + var itemsTotal = order.Items.Sum(item => item.Price * item.Quantity); + var shippingCost = itemsTotal > 50m ? 0m : order.ShippingCost; + + return new ProcessedOrder + { + Items = order.Items, + ShippingCost = shippingCost, + Total = itemsTotal + shippingCost + }; +} + +// Step 5: Refactor - Extract constants and improve readability +private const decimal FreeShippingThreshold = 50m; + +private static decimal CalculateItemsTotal(IEnumerable items) +{ + return items.Sum(item => item.Price * item.Quantity); +} + +private static bool QualifiesForFreeShipping(decimal itemsTotal) +{ + return itemsTotal > FreeShippingThreshold; +} + +public static ProcessedOrder ProcessOrder(Order order) +{ + var itemsTotal = CalculateItemsTotal(order.Items); + var shippingCost = QualifiesForFreeShipping(itemsTotal) ? 0m : order.ShippingCost; + + return new ProcessedOrder + { + Items = order.Items, + ShippingCost = shippingCost, + Total = itemsTotal + shippingCost + }; +} +``` + +### Testing Patterns + +#### xUnit and FluentAssertions + +```csharp +public class PaymentServiceTests +{ + private readonly Mock _paymentRepositoryMock; + private readonly Mock> _loggerMock; + private readonly PaymentService _paymentService; + + public PaymentServiceTests() + { + _paymentRepositoryMock = new Mock(); + _loggerMock = new Mock>(); + + var options = Options.Create(new PaymentOptions + { + MaxAmount = 10000m, + AcceptedCurrencies = new[] { "GBP", "USD", "EUR" } + }); + + _paymentService = new PaymentService( + _paymentRepositoryMock.Object, + new PaymentRequestValidator(), + _loggerMock.Object, + options); + } + + [Fact] + public async Task ProcessPaymentAsync_ShouldReturnFailure_WhenAmountIsNegative() + { + // Arrange + var request = new PaymentRequestBuilder() + .WithAmount(-100m) + .Build(); + + // Act + var result = await _paymentService.ProcessPaymentAsync(request); + + // Assert + result.IsFailure.Should().BeTrue(); + result.Should().BeOfType>(); + + var failure = result as Failure; + failure!.Error.Should().Contain("Amount must be greater than zero"); + } + + [Theory] + [InlineData(100)] + [InlineData(1000)] + [InlineData(10000)] + public async Task ProcessPaymentAsync_ShouldReturnSuccess_WhenRequestIsValid(decimal amount) + { + // Arrange + var request = new PaymentRequestBuilder() + .WithAmount(amount) + .Build(); + + // Act + var result = await _paymentService.ProcessPaymentAsync(request); + + // Assert + result.IsSuccess.Should().BeTrue(); + result.Should().BeOfType>(); + + var success = result as Success; + success!.Value.Amount.Should().Be(amount); + } +} +``` + +#### Integration Testing with Testcontainers (Completion) + +```csharp +public class PaymentApiTests : IAsyncLifetime +{ + private readonly WebApplicationFactory _factory; + private readonly HttpClient _client; + private readonly PostgreSqlContainer _postgres; + + public PaymentApiTests() + { + _postgres = new PostgreSqlBuilder() + .WithDatabase("testdb") + .WithUsername("testuser") + .WithPassword("testpass") + .Build(); + + _factory = new WebApplicationFactory() + .WithWebHostBuilder(builder => + { + builder.ConfigureTestServices(services => + { + // Replace the database connection + services.RemoveAll>(); + services.AddDbContext(options => + options.UseNpgsql(_postgres.GetConnectionString())); + }); + }); + + _client = _factory.CreateClient(); + } + + public async Task InitializeAsync() + { + await _postgres.StartAsync(); + + // Run migrations + using var scope = _factory.Services.CreateScope(); + var dbContext = scope.ServiceProvider.GetRequiredService(); + await dbContext.Database.MigrateAsync(); + } + + public async Task DisposeAsync() + { + await _factory.DisposeAsync(); + await _postgres.DisposeAsync(); + _client.Dispose(); + } + + [Fact] + public async Task PostPayment_ShouldReturnCreated_WhenRequestIsValid() + { + // Arrange + var paymentRequest = new PaymentRequestBuilder() + .WithAmount(150m) + .WithCurrency("GBP") + .Build(); + + var json = JsonSerializer.Serialize(paymentRequest); + var content = new StringContent(json, Encoding.UTF8, "application/json"); + + // Act + var response = await _client.PostAsync("/api/payments", content); + + // Assert + response.StatusCode.Should().Be(HttpStatusCode.Created); + + var responseContent = await response.Content.ReadAsStringAsync(); + var createdPayment = JsonSerializer.Deserialize(responseContent); + + createdPayment!.Amount.Should().Be(150m); + createdPayment.Currency.Should().Be("GBP"); + createdPayment.Status.Should().Be("Pending"); + } + + [Fact] + public async Task PostPayment_ShouldReturnBadRequest_WhenAmountIsInvalid() + { + // Arrange + var paymentRequest = new PaymentRequestBuilder() + .WithAmount(-50m) + .Build(); + + var json = JsonSerializer.Serialize(paymentRequest); + var content = new StringContent(json, Encoding.UTF8, "application/json"); + + // Act + var response = await _client.PostAsync("/api/payments", content); + + // Assert + response.StatusCode.Should().Be(HttpStatusCode.BadRequest); + + var responseContent = await response.Content.ReadAsStringAsync(); + responseContent.Should().Contain("Amount must be greater than zero"); + } +} +``` + +#### Testing with Redis and Message Queues + +```csharp +public class PaymentEventProcessorTests : IAsyncLifetime +{ + private readonly RedisContainer _redis; + private readonly RabbitMqContainer _rabbitMq; + private readonly IServiceCollection _services; + private readonly ServiceProvider _serviceProvider; + + public PaymentEventProcessorTests() + { + _redis = new RedisBuilder().Build(); + _rabbitMq = new RabbitMqBuilder().Build(); + + _services = new ServiceCollection(); + ConfigureServices(_services); + _serviceProvider = _services.BuildServiceProvider(); + } + + private void ConfigureServices(IServiceCollection services) + { + services.AddLogging(); + services.AddSingleton(provider => + ConnectionMultiplexer.Connect(_redis.GetConnectionString())); + + services.AddSingleton(provider => + { + var factory = new ConnectionFactory { Uri = new Uri(_rabbitMq.GetConnectionString()) }; + return factory.CreateConnection(); + }); + + services.AddScoped(); + services.AddScoped(); + } + + public async Task InitializeAsync() + { + await _redis.StartAsync(); + await _rabbitMq.StartAsync(); + } + + public async Task DisposeAsync() + { + await _serviceProvider.DisposeAsync(); + await _redis.DisposeAsync(); + await _rabbitMq.DisposeAsync(); + } + + [Fact] + public async Task ProcessPaymentEvent_ShouldUpdateCache_WhenPaymentCompleted() + { + // Arrange + using var scope = _serviceProvider.CreateScope(); + var processor = scope.ServiceProvider.GetRequiredService(); + var redis = scope.ServiceProvider.GetRequiredService(); + + var paymentId = PaymentId.New(); + var paymentEvent = new PaymentCompletedEvent(paymentId, 100m, "GBP", DateTime.UtcNow); + + // Act + await processor.ProcessAsync(paymentEvent); + + // Assert + var database = redis.GetDatabase(); + var cachedPayment = await database.StringGetAsync($"payment:{paymentId}"); + + cachedPayment.HasValue.Should().BeTrue(); + var payment = JsonSerializer.Deserialize(cachedPayment!); + payment!.Status.Should().Be("Completed"); + } +} +``` + +## API Development and Controllers + +### Minimal APIs (Preferred for Simple Endpoints) + +Use Minimal APIs for straightforward CRUD operations and simple endpoints: + +```csharp +// Program.cs +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); +builder.Services.AddPaymentServices(builder.Configuration); + +var app = builder.Build(); + +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); + +// Payment endpoints +app.MapPost("/api/payments", async ( + PaymentRequest request, + IPaymentService paymentService, + IValidator validator, + CancellationToken cancellationToken) => +{ + var validationResult = await validator.ValidateAsync(request, cancellationToken); + if (!validationResult.IsValid) + { + return Results.BadRequest(validationResult.Errors); + } + + var result = await paymentService.ProcessPaymentAsync(request, cancellationToken); + + return result switch + { + Success success => Results.Created($"/api/payments/{success.Value.Id}", success.Value), + Failure failure => Results.BadRequest(new { Error = failure.Error }), + _ => Results.Problem("An unexpected error occurred") + }; +}) +.WithName("CreatePayment") +.WithOpenApi(); + +app.MapGet("/api/payments/{id:guid}", async ( + Guid id, + IPaymentService paymentService, + CancellationToken cancellationToken) => +{ + var paymentId = new PaymentId(id); + var payment = await paymentService.GetPaymentAsync(paymentId, cancellationToken); + + return payment is not null + ? Results.Ok(payment) + : Results.NotFound(); +}) +.WithName("GetPayment") +.WithOpenApi(); + +app.MapGet("/api/payments", async ( + IPaymentService paymentService, + int page = 1, + int pageSize = 20, + CancellationToken cancellationToken = default) => +{ + var payments = await paymentService.GetPaymentsAsync(page, pageSize, cancellationToken); + return Results.Ok(payments); +}) +.WithName("GetPayments") +.WithOpenApi(); + +app.Run(); +``` + +### Controller-Based APIs (For Complex Logic) + +Use controllers when you need more complex routing, filters, or action-specific behavior: + +```csharp +[ApiController] +[Route("api/[controller]")] +[Produces("application/json")] +public class PaymentsController : ControllerBase +{ + private readonly IPaymentService _paymentService; + private readonly IValidator _validator; + private readonly ILogger _logger; + + public PaymentsController( + IPaymentService paymentService, + IValidator validator, + ILogger logger) + { + _paymentService = paymentService ?? throw new ArgumentNullException(nameof(paymentService)); + _validator = validator ?? throw new ArgumentNullException(nameof(validator)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } + + /// + /// Creates a new payment + /// + /// Payment details + /// Cancellation token + /// Created payment + [HttpPost] + [ProducesResponseType(StatusCodes.Status201Created)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async Task> CreatePayment( + [FromBody] PaymentRequest request, + CancellationToken cancellationToken = default) + { + var validationResult = await _validator.ValidateAsync(request, cancellationToken); + if (!validationResult.IsValid) + { + var problemDetails = new ValidationProblemDetails(); + foreach (var error in validationResult.Errors) + { + problemDetails.Errors.Add(error.PropertyName, new[] { error.ErrorMessage }); + } + return BadRequest(problemDetails); + } + + var result = await _paymentService.ProcessPaymentAsync(request, cancellationToken); + + return result switch + { + Success success => CreatedAtAction( + nameof(GetPayment), + new { id = success.Value.Id.Value }, + PaymentResponse.FromPayment(success.Value)), + Failure failure => BadRequest(new ProblemDetails + { + Title = "Payment processing failed", + Detail = failure.Error, + Status = StatusCodes.Status400BadRequest + }), + _ => StatusCode(StatusCodes.Status500InternalServerError) + }; + } + + /// + /// Gets a payment by ID + /// + /// Payment ID + /// Cancellation token + /// Payment details + [HttpGet("{id:guid}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task> GetPayment( + [FromRoute] Guid id, + CancellationToken cancellationToken = default) + { + var paymentId = new PaymentId(id); + var payment = await _paymentService.GetPaymentAsync(paymentId, cancellationToken); + + if (payment is null) + { + return NotFound(new ProblemDetails + { + Title = "Payment not found", + Detail = $"Payment with ID {id} was not found", + Status = StatusCodes.Status404NotFound + }); + } + + return Ok(PaymentResponse.FromPayment(payment)); + } + + /// + /// Gets a paginated list of payments + /// + /// Pagination and filter parameters + /// Cancellation token + /// Paginated payment list + [HttpGet] + [ProducesResponseType>(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status400BadRequest)] + public async Task>> GetPayments( + [FromQuery] GetPaymentsRequest request, + CancellationToken cancellationToken = default) + { + var validator = new GetPaymentsRequestValidator(); + var validationResult = await validator.ValidateAsync(request, cancellationToken); + + if (!validationResult.IsValid) + { + var problemDetails = new ValidationProblemDetails(); + foreach (var error in validationResult.Errors) + { + problemDetails.Errors.Add(error.PropertyName, new[] { error.ErrorMessage }); + } + return BadRequest(problemDetails); + } + + var payments = await _paymentService.GetPaymentsAsync( + request.Page, + request.PageSize, + request.Status, + request.FromDate, + request.ToDate, + cancellationToken); + + var response = new PagedResponse + { + Data = payments.Data.Select(PaymentResponse.FromPayment).ToList(), + Page = payments.Page, + PageSize = payments.PageSize, + TotalCount = payments.TotalCount, + TotalPages = payments.TotalPages + }; + + return Ok(response); + } +} +``` + +### Response Models and DTOs + +Create dedicated response models that don't expose internal domain structure: + +```csharp +public record PaymentResponse +{ + public Guid Id { get; init; } + public decimal Amount { get; init; } + public string Currency { get; init; } = string.Empty; + public string Status { get; init; } = string.Empty; + public DateTime CreatedAt { get; init; } + public DateTime? ProcessedAt { get; init; } + public string? Description { get; init; } + public Dictionary? Metadata { get; init; } + + public static PaymentResponse FromPayment(Payment payment) + { + return new PaymentResponse + { + Id = payment.Id.Value, + Amount = payment.Amount, + Currency = payment.Currency, + Status = payment.Status.ToString(), + CreatedAt = payment.CreatedAt, + ProcessedAt = payment.ProcessedAt, + Description = payment.Description, + Metadata = payment.Metadata + }; + } +} + +public record GetPaymentsRequest +{ + public int Page { get; init; } = 1; + public int PageSize { get; init; } = 20; + public string? Status { get; init; } + public DateTime? FromDate { get; init; } + public DateTime? ToDate { get; init; } +} + +public record PagedResponse +{ + public IReadOnlyList Data { get; init; } = Array.Empty(); + public int Page { get; init; } + public int PageSize { get; init; } + public int TotalCount { get; init; } + public int TotalPages { get; init; } + public bool HasNextPage => Page < TotalPages; + public bool HasPreviousPage => Page > 1; +} + +public class GetPaymentsRequestValidator : AbstractValidator +{ + public GetPaymentsRequestValidator() + { + RuleFor(x => x.Page) + .GreaterThan(0) + .WithMessage("Page must be greater than 0"); + + RuleFor(x => x.PageSize) + .GreaterThan(0) + .LessThanOrEqualTo(100) + .WithMessage("Page size must be between 1 and 100"); + + RuleFor(x => x.FromDate) + .LessThanOrEqualTo(x => x.ToDate) + .When(x => x.FromDate.HasValue && x.ToDate.HasValue) + .WithMessage("From date cannot be later than to date"); + + RuleFor(x => x.Status) + .Must(BeValidStatus) + .When(x => !string.IsNullOrEmpty(x.Status)) + .WithMessage("Status must be one of: Pending, Processing, Completed, Failed"); + } + + private static bool BeValidStatus(string? status) + { + if (string.IsNullOrEmpty(status)) + return true; + + var validStatuses = new[] { "Pending", "Processing", "Completed", "Failed" }; + return validStatuses.Contains(status, StringComparer.OrdinalIgnoreCase); + } +} +``` + +### Global Error Handling + +Implement consistent error handling across the API: + +```csharp +public class GlobalExceptionMiddleware +{ + private readonly RequestDelegate _next; + private readonly ILogger _logger; + private readonly IHostEnvironment _environment; + + public GlobalExceptionMiddleware( + RequestDelegate next, + ILogger logger, + IHostEnvironment environment) + { + _next = next; + _logger = logger; + _environment = environment; + } + + public async Task InvokeAsync(HttpContext context) + { + try + { + await _next(context); + } + catch (Exception ex) + { + _logger.LogError(ex, "An unhandled exception occurred while processing the request"); + await HandleExceptionAsync(context, ex); + } + } + + private async Task HandleExceptionAsync(HttpContext context, Exception exception) + { + context.Response.ContentType = "application/json"; + + var problemDetails = exception switch + { + ArgumentException argEx => new ProblemDetails + { + Title = "Invalid argument", + Detail = argEx.Message, + Status = StatusCodes.Status400BadRequest + }, + InvalidOperationException invalidOpEx => new ProblemDetails + { + Title = "Invalid operation", + Detail = invalidOpEx.Message, + Status = StatusCodes.Status409Conflict + }, + UnauthorizedAccessException => new ProblemDetails + { + Title = "Unauthorized", + Detail = "You are not authorized to access this resource", + Status = StatusCodes.Status401Unauthorized + }, + _ => new ProblemDetails + { + Title = "An error occurred", + Detail = _environment.IsDevelopment() ? exception.Message : "An unexpected error occurred", + Status = StatusCodes.Status500InternalServerError + } + }; + + problemDetails.Instance = context.Request.Path; + problemDetails.Extensions.Add("traceId", context.TraceIdentifier); + + if (_environment.IsDevelopment() && exception is not ArgumentException) + { + problemDetails.Extensions.Add("stackTrace", exception.StackTrace); + } + + context.Response.StatusCode = problemDetails.Status ?? StatusCodes.Status500InternalServerError; + + var json = JsonSerializer.Serialize(problemDetails, new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }); + + await context.Response.WriteAsync(json); + } +} + +// Register in Program.cs +app.UseMiddleware(); +``` + +## Data Access and Entity Framework + +### Entity Configuration + +Use explicit configuration over conventions for clarity and maintainability: + +```csharp +public class PaymentConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("payments"); + + builder.HasKey(p => p.Id); + + builder.Property(p => p.Id) + .HasConversion( + id => id.Value, + value => new PaymentId(value)) + .ValueGeneratedNever(); + + builder.Property(p => p.Amount) + .HasColumnType("decimal(18,2)") + .IsRequired(); + + builder.Property(p => p.Currency) + .HasMaxLength(3) + .IsRequired(); + + builder.Property(p => p.Status) + .HasConversion() + .HasMaxLength(20) + .IsRequired(); + + builder.Property(p => p.CreatedAt) + .IsRequired(); + + builder.Property(p => p.ProcessedAt) + .IsRequired(false); + + builder.Property(p => p.Description) + .HasMaxLength(500) + .IsRequired(false); + + builder.Property(p => p.Metadata) + .HasConversion( + metadata => metadata != null ? JsonSerializer.Serialize(metadata, (JsonSerializerOptions?)null) : null, + json => json != null ? JsonSerializer.Deserialize>(json, (JsonSerializerOptions?)null) : null) + .HasColumnType("jsonb") + .IsRequired(false); + + builder.Property(p => p.CustomerId) + .HasConversion( + id => id.Value, + value => new CustomerId(value)) + .IsRequired(); + + builder.Property(p => p.CardId) + .HasMaxLength(50) + .IsRequired(); + + // Indexes + builder.HasIndex(p => p.Status); + builder.HasIndex(p => p.CustomerId); + builder.HasIndex(p => p.CreatedAt); + builder.HasIndex(p => new { p.CustomerId, p.CreatedAt }); + } +} + +public class CustomerConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("customers"); + + builder.HasKey(c => c.Id); + + builder.Property(c => c.Id) + .HasConversion( + id => id.Value, + value => new CustomerId(value)) + .ValueGeneratedNever(); + + builder.Property(c => c.Email) + .HasMaxLength(320) + .IsRequired(); + + builder.Property(c => c.FirstName) + .HasMaxLength(100) + .IsRequired(); + + builder.Property(c => c.LastName) + .HasMaxLength(100) + .IsRequired(); + + builder.OwnsOne(c => c.Address, addressBuilder => + { + addressBuilder.Property(a => a.HouseNumber) + .HasColumnName("address_house_number") + .HasMaxLength(20) + .IsRequired(); + + addressBuilder.Property(a => a.HouseName) + .HasColumnName("address_house_name") + .HasMaxLength(100) + .IsRequired(false); + + addressBuilder.Property(a => a.AddressLine1) + .HasColumnName("address_line_1") + .HasMaxLength(200) + .IsRequired(); + + addressBuilder.Property(a => a.AddressLine2) + .HasColumnName("address_line_2") + .HasMaxLength(200) + .IsRequired(false); + + addressBuilder.Property(a => a.City) + .HasColumnName("address_city") + .HasMaxLength(100) + .IsRequired(); + + addressBuilder.Property(a => a.Postcode) + .HasColumnName("address_postcode") + .HasMaxLength(20) + .IsRequired(); + }); + + builder.Property(c => c.CreatedAt) + .IsRequired(); + + builder.Property(c => c.UpdatedAt) + .IsRequired(); + + // Indexes + builder.HasIndex(c => c.Email) + .IsUnique(); + builder.HasIndex(c => c.CreatedAt); + } +} +``` + +### DbContext Configuration + +```csharp +public class PaymentDbContext : DbContext +{ + public PaymentDbContext(DbContextOptions options) : base(options) + { + } + + public DbSet Payments => Set(); + public DbSet Customers => Set(); + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + // Apply all configurations in the assembly + modelBuilder.ApplyConfigurationsFromAssembly(typeof(PaymentDbContext).Assembly); + + // Global query filters + modelBuilder.Entity() + .HasQueryFilter(p => !p.IsDeleted); + + modelBuilder.Entity() + .HasQueryFilter(c => !c.IsDeleted); + } + + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + if (!optionsBuilder.IsConfigured) + { + // This should only be used for design-time operations + optionsBuilder.UseNpgsql("Host=localhost;Database=payments_dev;Username=dev;Password=dev"); + } + + // Enable sensitive data logging only in development + optionsBuilder.EnableSensitiveDataLogging(false); + optionsBuilder.EnableDetailedErrors(true); + } + + public override async Task SaveChangesAsync(CancellationToken cancellationToken = default) + { + // Automatically set audit fields + var entries = ChangeTracker.Entries() + .Where(e => e.Entity is IAuditable && e.State is EntityState.Added or EntityState.Modified); + + foreach (var entry in entries) + { + var auditable = (IAuditable)entry.Entity; + + if (entry.State == EntityState.Added) + { + auditable.CreatedAt = DateTime.UtcNow; + } + + auditable.UpdatedAt = DateTime.UtcNow; + } + + return await base.SaveChangesAsync(cancellationToken); + } +} +``` + +### Repository Pattern + +Implement repository pattern for complex queries and data access abstraction: + +```csharp +public interface IPaymentRepository +{ + Task GetByIdAsync(PaymentId id, CancellationToken cancellationToken = default); + Task> GetByCustomerIdAsync(CustomerId customerId, CancellationToken cancellationToken = default); + Task> GetPagedAsync(int page, int pageSize, PaymentStatus? status = null, + DateTime? fromDate = null, DateTime? toDate = null, CancellationToken cancellationToken = default); + Task AddAsync(Payment payment, CancellationToken cancellationToken = default); + Task UpdateAsync(Payment payment, CancellationToken cancellationToken = default); + Task DeleteAsync(PaymentId id, CancellationToken cancellationToken = default); + Task ExistsAsync(PaymentId id, CancellationToken cancellationToken = default); + Task GetTotalAmountByCustomerAsync(CustomerId customerId, DateTime fromDate, DateTime toDate, + CancellationToken cancellationToken = default); +} + +public class PaymentRepository : IPaymentRepository +{ + private readonly PaymentDbContext _context; + private readonly ILogger _logger; + + public PaymentRepository(PaymentDbContext context, ILogger logger) + { + _context = context ?? throw new ArgumentNullException(nameof(context)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } + + public async Task GetByIdAsync(PaymentId id, CancellationToken cancellationToken = default) + { + return await _context.Payments + .FirstOrDefaultAsync(p => p.Id == id, cancellationToken); + } + + public async Task> GetByCustomerIdAsync(CustomerId customerId, CancellationToken cancellationToken = default) + { + return await _context.Payments + .Where(p => p.CustomerId == customerId) + .OrderByDescending(p => p.CreatedAt) + .ToListAsync(cancellationToken); + } + + public async Task> GetPagedAsync( + int page, + int pageSize, + PaymentStatus? status = null, + DateTime? fromDate = null, + DateTime? toDate = null, + CancellationToken cancellationToken = default) + { + var query = _context.Payments.AsQueryable(); + + if (status.HasValue) + { + query = query.Where(p => p.Status == status.Value); + } + + if (fromDate.HasValue) + { + query = query.Where(p => p.CreatedAt >= fromDate.Value); + } + + if (toDate.HasValue) + { + query = query.Where(p => p.CreatedAt <= toDate.Value); + } + + var totalCount = await query.CountAsync(cancellationToken); + + var payments = await query + .OrderByDescending(p => p.CreatedAt) + .Skip((page - 1) * pageSize) + .Take(pageSize) + .ToListAsync(cancellationToken); + + return new PagedResult + { + Data = payments, + Page = page, + PageSize = pageSize, + TotalCount = totalCount, + TotalPages = (int)Math.Ceiling((double)totalCount / pageSize) + }; + } + + public async Task AddAsync(Payment payment, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(payment); + + _context.Payments.Add(payment); + await _context.SaveChangesAsync(cancellationToken); + + _logger.LogInformation("Payment {PaymentId} added successfully", payment.Id); + } + + public async Task UpdateAsync(Payment payment, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(payment); + + _context.Payments.Update(payment); + await _context.SaveChangesAsync(cancellationToken); + + _logger.LogInformation("Payment {PaymentId} updated successfully", payment.Id); + } + + public async Task DeleteAsync(PaymentId id, CancellationToken cancellationToken = default) + { + var payment = await GetByIdAsync(id, cancellationToken); + if (payment is not null) + { + payment.MarkAsDeleted(); + await UpdateAsync(payment, cancellationToken); + + _logger.LogInformation("Payment {PaymentId} marked as deleted", id); + } + } + + public async Task ExistsAsync(PaymentId id, CancellationToken cancellationToken = default) + { + return await _context.Payments + .AnyAsync(p => p.Id == id, cancellationToken); + } + + public async Task GetTotalAmountByCustomerAsync( + CustomerId customerId, + DateTime fromDate, + DateTime toDate, + CancellationToken cancellationToken = default) + { + return await _context.Payments + .Where(p => p.CustomerId == customerId) + .Where(p => p.CreatedAt >= fromDate && p.CreatedAt <= toDate) + .Where(p => p.Status == PaymentStatus.Completed) + .SumAsync(p => p.Amount, cancellationToken); + } +} +``` + +### Database Migrations and Seeding + +```csharp +// Migration helper for consistent database setup +public static class DatabaseExtensions +{ + public static async Task MigrateDatabaseAsync(this WebApplication app) + { + using var scope = app.Services.CreateScope(); + var context = scope.ServiceProvider.GetRequiredService(); + var logger = scope.ServiceProvider.GetRequiredService>(); + + try + { + logger.LogInformation("Starting database migration"); + await context.Database.MigrateAsync(); + logger.LogInformation("Database migration completed successfully"); + + if (app.Environment.IsDevelopment()) + { + await SeedDevelopmentDataAsync(context, logger); + } + } + catch (Exception ex) + { + logger.LogError(ex, "An error occurred while migrating the database"); + throw; + } + + return app; + } + + private static async Task SeedDevelopmentDataAsync(PaymentDbContext context, ILogger logger) + { + logger.LogInformation("Seeding development data"); + + // Check if data already exists + if (await context.Customers.AnyAsync()) + { + logger.LogInformation("Development data already exists, skipping seed"); + return; + } + + // Seed customers + var customers = new[] + { + new Customer( + CustomerId.New(), + "john.doe@example.com", + "John", + "Doe", + new AddressDetails("123", "Test House", "Test Street", null, "London", "SW1A 1AA")), + new Customer( + CustomerId.New(), + "jane.smith@example.com", + "Jane", + "Smith", + new AddressDetails("456", null, "Another Street", "Apt 2", "Manchester", "M1 1AA")) + }; + + context.Customers.AddRange(customers); + await context.SaveChangesAsync(); + + // Seed payments + var payments = customers.SelectMany(customer => new[] + { + new Payment(PaymentId.New(), 100m, "GBP", customer.Id, "card_123"), + new Payment(PaymentId.New(), 250m, "USD", customer.Id, "card_456"), + new Payment(PaymentId.New(), 75m, "EUR", customer.Id, "card_789") + }).ToArray(); + + context.Payments.AddRange(payments); + await context.SaveChangesAsync(); + + logger.LogInformation("Development data seeded successfully"); + } +} + +// Usage in Program.cs +await app.MigrateDatabaseAsync(); +``` + +### Unit of Work Pattern (Optional) + +```csharp +public interface IUnitOfWork : IDisposable +{ + IPaymentRepository Payments { get; } + ICustomerRepository Customers { get; } + Task SaveChangesAsync(CancellationToken cancellationToken = default); + Task BeginTransactionAsync(CancellationToken cancellationToken = default); + Task CommitTransactionAsync(CancellationToken cancellationToken = default); + Task RollbackTransactionAsync(CancellationToken cancellationToken = default); +} + +public class UnitOfWork : IUnitOfWork +{ + private readonly PaymentDbContext _context; + private IDbContextTransaction? _transaction; + + public UnitOfWork(PaymentDbContext context) + { + _context = context ?? throw new ArgumentNullException(nameof(context)); + Payments = new PaymentRepository(_context, serviceProvider.GetRequiredService>()); + Customers = new CustomerRepository(_context, serviceProvider.GetRequiredService>()); + } + + public IPaymentRepository Payments { get; } + public ICustomerRepository Customers { get; } + + public async Task SaveChangesAsync(CancellationToken cancellationToken = default) + { + return await _context.SaveChangesAsync(cancellationToken); + } + + public async Task BeginTransactionAsync(CancellationToken cancellationToken = default) + { + _transaction = await _context.Database.BeginTransactionAsync(cancellationToken); + } + + public async Task CommitTransactionAsync(CancellationToken cancellationToken = default) + { + if (_transaction is not null) + { + await _transaction.CommitAsync(cancellationToken); + await _transaction.DisposeAsync(); + _transaction = null; + } + } + + public async Task RollbackTransactionAsync(CancellationToken cancellationToken = default) + { + if (_transaction is not null) + { + await _transaction.RollbackAsync(cancellationToken); + await _transaction.DisposeAsync(); + _transaction = null; + } + } + + public void Dispose() + { + _transaction?.Dispose(); + _context.Dispose(); + } +} +``` +## Refactoring - The Critical Third Step + +Evaluating refactoring opportunities is not optional - it's the third step in the TDD cycle. After achieving a green state and committing your work, you MUST assess whether the code can be improved. However, only refactor if there's clear value - if the code is already clean and expresses intent well, move on to the next test. + +#### What is Refactoring? + +Refactoring means changing the internal structure of code without changing its external behavior. The public API remains unchanged, all tests continue to pass, but the code becomes cleaner, more maintainable, or more efficient. Remember: only refactor when it genuinely improves the code - not all code needs refactoring. + +#### When to Refactor + +- **Always assess after green**: Once tests pass, before moving to the next test, evaluate if refactoring would add value +- **When you see duplication**: But understand what duplication really means (see DRY below) +- **When names could be clearer**: Variable names, method names, or type names that don't clearly express intent +- **When structure could be simpler**: Complex conditional logic, deeply nested code, or long methods +- **When patterns emerge**: After implementing several similar features, useful abstractions may become apparent + +**Remember**: Not all code needs refactoring. If the code is already clean, expressive, and well-structured, commit and move on. Refactoring should improve the code - don't change things just for the sake of change. + +#### Refactoring Guidelines + +##### 1. Commit Before Refactoring + +Always commit your working code before starting any refactoring. This gives you a safe point to return to: + +```bash +git add . +git commit -m "feat: add payment validation" +# Now safe to refactor +``` + +##### 2. Look for Useful Abstractions Based on Semantic Meaning + +Create abstractions only when code shares the same semantic meaning and purpose. Don't abstract based on structural similarity alone - **duplicate code is far cheaper than the wrong abstraction**. + +```csharp +// Similar structure, DIFFERENT semantic meaning - DO NOT ABSTRACT +private static bool ValidatePaymentAmount(decimal amount) +{ + return amount > 0 && amount <= 10000; +} + +private static bool ValidateTransferAmount(decimal amount) +{ + return amount > 0 && amount <= 10000; +} + +// These might have the same structure today, but they represent different +// business concepts that will likely evolve independently. +// Payment limits might change based on fraud rules. +// Transfer limits might change based on account type. +// Abstracting them couples unrelated business rules. + +// Similar structure, SAME semantic meaning - SAFE TO ABSTRACT +private static string FormatUserDisplayName(string firstName, string lastName) +{ + return $"{firstName} {lastName}".Trim(); +} + +private static string FormatCustomerDisplayName(string firstName, string lastName) +{ + return $"{firstName} {lastName}".Trim(); +} + +private static string FormatEmployeeDisplayName(string firstName, string lastName) +{ + return $"{firstName} {lastName}".Trim(); +} + +// These all represent the same concept: "how we format a person's name for display" +// They share semantic meaning, not just structure +private static string FormatPersonDisplayName(string firstName, string lastName) +{ + return $"{firstName} {lastName}".Trim(); +} + +// Replace all call sites throughout the codebase: +// Before: +// var userLabel = FormatUserDisplayName(user.FirstName, user.LastName); +// var customerName = FormatCustomerDisplayName(customer.FirstName, customer.LastName); +// var employeeTag = FormatEmployeeDisplayName(employee.FirstName, employee.LastName); + +// After: +// var userLabel = FormatPersonDisplayName(user.FirstName, user.LastName); +// var customerName = FormatPersonDisplayName(customer.FirstName, customer.LastName); +// var employeeTag = FormatPersonDisplayName(employee.FirstName, employee.LastName); + +// Then remove the original methods as they're no longer needed +``` + +**Questions to ask before abstracting:** + +- Do these code blocks represent the same concept or different concepts that happen to look similar? +- If the business rules for one change, should the others change too? +- Would a developer reading this abstraction understand why these things are grouped together? +- Am I abstracting based on what the code IS (structure) or what it MEANS (semantics)? + +**Remember**: It's much easier to create an abstraction later when the semantic relationship becomes clear than to undo a bad abstraction that couples unrelated concepts. + +##### 3. Understanding DRY - It's About Knowledge, Not Code + +DRY (Don't Repeat Yourself) is about not duplicating **knowledge** in the system, not about eliminating all code that looks similar. + +```csharp +// This is NOT a DRY violation - different knowledge despite similar code +private static bool ValidateUserAge(int age) +{ + return age >= 18 && age <= 100; +} + +private static bool ValidateProductRating(int rating) +{ + return rating >= 1 && rating <= 5; +} + +private static bool ValidateYearsOfExperience(int years) +{ + return years >= 0 && years <= 50; +} + +// These represent different business concepts with different ranges and reasons: +// - User age: based on legal requirements and realistic human lifespan +// - Product rating: based on UI design (5-star system) +// - Years of experience: based on realistic career length +// Don't abstract them just because they look similar! + +// This IS a DRY violation - same knowledge expressed multiple times +public static class PaymentLimits +{ + public static bool IsValidAmount(decimal amount) => amount > 0 && amount <= 10000; +} + +public static class RefundLimits +{ + public static bool IsValidAmount(decimal amount) => amount > 0 && amount <= 10000; +} + +// Both represent the same business rule: "transaction amount limits" +// This should be consolidated into a single source of truth: +public static class TransactionLimits +{ + private const decimal MinAmount = 0; + private const decimal MaxAmount = 10000; + + public static bool IsValidAmount(decimal amount) => amount > MinAmount && amount <= MaxAmount; +} +``` + +##### 4. Extracting Methods vs. Extracting Classes + +Start by extracting methods within the same class. Only extract to new classes when you have a cohesive set of related methods and data. + +```csharp +// Start here: Long method doing multiple things +public async Task ProcessPaymentAsync(PaymentRequest request) +{ + // Validation logic (20 lines) + if (string.IsNullOrEmpty(request.CardNumber)) + return PaymentResult.Invalid("Card number is required"); + if (request.Amount <= 0) + return PaymentResult.Invalid("Amount must be positive"); + // ... more validation + + // Authorization logic (15 lines) + var authRequest = new AuthorizationRequest + { + CardNumber = request.CardNumber, + Amount = request.Amount, + Currency = request.Currency + }; + var authResult = await _authorizationService.AuthorizeAsync(authRequest); + if (!authResult.IsSuccessful) + return PaymentResult.Failed(authResult.ErrorMessage); + + // Capture logic (10 lines) + var captureRequest = new CaptureRequest + { + AuthorizationId = authResult.AuthorizationId, + Amount = request.Amount + }; + var captureResult = await _captureService.CaptureAsync(captureRequest); + // ... etc +} + +// Step 1: Extract methods (keep in same class) +public async Task ProcessPaymentAsync(PaymentRequest request) +{ + var validationResult = ValidatePaymentRequest(request); + if (!validationResult.IsValid) + return PaymentResult.Invalid(validationResult.ErrorMessage); + + var authorizationResult = await AuthorizePaymentAsync(request); + if (!authorizationResult.IsSuccessful) + return PaymentResult.Failed(authorizationResult.ErrorMessage); + + var captureResult = await CapturePaymentAsync(authorizationResult.AuthorizationId, request.Amount); + return captureResult.IsSuccessful + ? PaymentResult.Success(captureResult.PaymentId) + : PaymentResult.Failed(captureResult.ErrorMessage); +} + +private ValidationResult ValidatePaymentRequest(PaymentRequest request) +{ + // Validation logic extracted to method +} + +private async Task AuthorizePaymentAsync(PaymentRequest request) +{ + // Authorization logic extracted to method +} + +private async Task CapturePaymentAsync(string authorizationId, decimal amount) +{ + // Capture logic extracted to method +} + +// Step 2: Only if these methods grow and need shared state, extract to class +public class PaymentProcessor +{ + // Only extract to class when methods are cohesive and share state +} +``` + +##### 5. When NOT to Refactor + +```csharp +// Don't refactor just because code is long if it's already clear +public static PaymentValidationResult ValidatePayment(PaymentRequest request) +{ + var errors = new List(); + + if (string.IsNullOrWhiteSpace(request.CardNumber)) + errors.Add("Card number is required"); + + if (request.CardNumber?.Length != 16) + errors.Add("Card number must be 16 digits"); + + if (string.IsNullOrWhiteSpace(request.ExpiryDate)) + errors.Add("Expiry date is required"); + + if (!IsValidExpiryDate(request.ExpiryDate)) + errors.Add("Expiry date must be in MM/YY format and not expired"); + + if (string.IsNullOrWhiteSpace(request.Cvv)) + errors.Add("CVV is required"); + + if (request.Cvv?.Length is not (3 or 4)) + errors.Add("CVV must be 3 or 4 digits"); + + if (request.Amount <= 0) + errors.Add("Amount must be greater than zero"); + + if (request.Amount > 10000) + errors.Add("Amount cannot exceed £10,000"); + + return errors.Count == 0 + ? PaymentValidationResult.Valid() + : PaymentValidationResult.Invalid(errors); +} + +// This method is long but perfectly clear - don't refactor it! +// Each line does exactly one validation check +// The structure is consistent and easy to follow +// Breaking it up would make it harder to understand +``` + +## Performance and Optimization + +### Async/Await Best Practices + +```csharp +// Good - Proper async/await usage +public async Task ProcessPaymentAsync(PaymentRequest request, CancellationToken cancellationToken = default) +{ + var payment = await ValidateAndCreatePaymentAsync(request, cancellationToken); + + var authResult = await _authorizationService.AuthorizeAsync(payment.ToAuthRequest(), cancellationToken); + if (!authResult.IsSuccess) + { + return PaymentResult.Failed(authResult.Error); + } + + var captureResult = await _captureService.CaptureAsync(authResult.AuthorizationId, cancellationToken); + return PaymentResult.Success(captureResult.PaymentId); +} + +// Avoid - Blocking on async code +public PaymentResult ProcessPayment(PaymentRequest request) +{ + // NEVER do this - it can cause deadlocks + var result = ProcessPaymentAsync(request).Result; + return result; +} + +// Good - Parallel execution when operations are independent +public async Task GetCustomerSummaryAsync(CustomerId customerId, CancellationToken cancellationToken = default) +{ + var customerTask = _customerRepository.GetByIdAsync(customerId, cancellationToken); + var paymentsTask = _paymentRepository.GetByCustomerIdAsync(customerId, cancellationToken); + var ordersTask = _orderRepository.GetByCustomerIdAsync(customerId, cancellationToken); + + await Task.WhenAll(customerTask, paymentsTask, ordersTask); + + var customer = await customerTask; + var payments = await paymentsTask; + var orders = await ordersTask; + + return new CustomerSummary(customer, payments, orders); +} + +// Good - ConfigureAwait(false) in library code, but not required if building an application. +public async Task CreatePaymentAsync(PaymentRequest request, CancellationToken cancellationToken = default) +{ + var payment = Payment.Create(request); + + await _paymentRepository.AddAsync(payment, cancellationToken).ConfigureAwait(false); + await _eventPublisher.PublishAsync(new PaymentCreatedEvent(payment.Id), cancellationToken).ConfigureAwait(false); + + return payment; +} + +// Good - Proper cancellation token usage +public async Task> GetPaymentsAsync( + CustomerId customerId, + CancellationToken cancellationToken = default) +{ + cancellationToken.ThrowIfCancellationRequested(); + + return await _context.Payments + .Where(p => p.CustomerId == customerId) + .ToListAsync(cancellationToken); +} +``` + +### Memory Management and Resource Disposal + +```csharp +// Good - Proper disposal with using statements +public async Task GeneratePaymentReportAsync(ReportRequest request, CancellationToken cancellationToken = default) +{ + using var connection = await _connectionFactory.CreateConnectionAsync(cancellationToken); + using var command = connection.CreateCommand(); + + command.CommandText = "SELECT * FROM payments WHERE created_at BETWEEN @start AND @end"; + command.Parameters.Add(new SqlParameter("@start", request.StartDate)); + command.Parameters.Add(new SqlParameter("@end", request.EndDate)); + + using var reader = await command.ExecuteReaderAsync(cancellationToken); + + var memoryStream = new MemoryStream(); + await WriteReportToStreamAsync(reader, memoryStream, cancellationToken); + + memoryStream.Position = 0; + return memoryStream; +} + +// Good - IAsyncDisposable for async cleanup +public sealed class PaymentProcessor : IAsyncDisposable +{ + private readonly HttpClient _httpClient; + private readonly IServiceScope _scope; + private bool _disposed; + + public PaymentProcessor(HttpClient httpClient, IServiceScope scope) + { + _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); + _scope = scope ?? throw new ArgumentNullException(nameof(scope)); + } + + public async Task ProcessAsync(PaymentRequest request, CancellationToken cancellationToken = default) + { + ObjectDisposedException.ThrowIf(_disposed, this); + + // Processing logic... + return PaymentResult.Success(); + } + + public async ValueTask DisposeAsync() + { + if (_disposed) + return; + + try + { + _httpClient?.Dispose(); + + if (_scope is IAsyncDisposable asyncDisposableScope) + { + await asyncDisposableScope.DisposeAsync(); + } + else + { + _scope?.Dispose(); + } + } + finally + { + _disposed = true; + } + } +} + +// Good - Struct for small, immutable data to reduce allocations +public readonly record struct PaymentId(Guid Value) +{ + public static PaymentId New() => new(Guid.NewGuid()); + public static PaymentId Parse(ReadOnlySpan value) => new(Guid.Parse(value)); + public override string ToString() => Value.ToString(); +} + +// Good - Span and Memory for efficient string operations +public static class PaymentCardHelper +{ + public static string MaskCardNumber(ReadOnlySpan cardNumber) + { + if (cardNumber.Length != 16) + throw new ArgumentException("Card number must be 16 digits", nameof(cardNumber)); + + Span masked = stackalloc char[19]; // 16 digits + 3 spaces + + // Copy first 4 digits + cardNumber[..4].CopyTo(masked); + masked[4] = ' '; + + // Mask middle 8 digits + "****".AsSpan().CopyTo(masked[5..]); + masked[9] = ' '; + "****".AsSpan().CopyTo(masked[10..]); + masked[14] = ' '; + + // Copy last 4 digits + cardNumber[12..].CopyTo(masked[15..]); + + return new string(masked); + } +} +``` + +### Caching Strategies + +Caching is not required in all application use cases, always confirm with the developer before implementing caching. + +```csharp +// Good - Memory caching with proper cache keys and expiration +public class PaymentService : IPaymentService +{ + private readonly IPaymentRepository _paymentRepository; + private readonly IMemoryCache _memoryCache; + private readonly IDistributedCache _distributedCache; + private readonly ILogger _logger; + + private static readonly TimeSpan CustomerCacheExpiry = TimeSpan.FromMinutes(15); + private static readonly TimeSpan PaymentCacheExpiry = TimeSpan.FromMinutes(5); + + public PaymentService( + IPaymentRepository paymentRepository, + IMemoryCache memoryCache, + IDistributedCache distributedCache, + ILogger logger) + { + _paymentRepository = paymentRepository; + _memoryCache = memoryCache; + _distributedCache = distributedCache; + _logger = logger; + } + + public async Task GetCustomerAsync(CustomerId customerId, CancellationToken cancellationToken = default) + { + var cacheKey = $"customer:{customerId}"; + + // Try memory cache first + if (_memoryCache.TryGetValue(cacheKey, out Customer? cachedCustomer)) + { + _logger.LogDebug("Customer {CustomerId} found in memory cache", customerId); + return cachedCustomer; + } + + // Try distributed cache + var distributedCacheValue = await _distributedCache.GetStringAsync(cacheKey, cancellationToken); + if (!string.IsNullOrEmpty(distributedCacheValue)) + { + var customer = JsonSerializer.Deserialize(distributedCacheValue); + + // Add to memory cache for faster future access + _memoryCache.Set(cacheKey, customer, CustomerCacheExpiry); + + _logger.LogDebug("Customer {CustomerId} found in distributed cache", customerId); + return customer; + } + + // Fetch from repository + var customerFromDb = await _customerRepository.GetByIdAsync(customerId, cancellationToken); + if (customerFromDb is not null) + { + // Cache in both memory and distributed cache + _memoryCache.Set(cacheKey, customerFromDb, CustomerCacheExpiry); + + var serializedCustomer = JsonSerializer.Serialize(customerFromDb); + await _distributedCache.SetStringAsync( + cacheKey, + serializedCustomer, + new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = CustomerCacheExpiry }, + cancellationToken); + + _logger.LogDebug("Customer {CustomerId} cached from database", customerId); + } + + return customerFromDb; + } + + public async Task InvalidateCustomerCacheAsync(CustomerId customerId, CancellationToken cancellationToken = default) + { + var cacheKey = $"customer:{customerId}"; + + _memoryCache.Remove(cacheKey); + await _distributedCache.RemoveAsync(cacheKey, cancellationToken); + + _logger.LogDebug("Customer {CustomerId} cache invalidated", customerId); + } +} + +// Good - Cache-aside pattern with cache warming +public class PaymentAnalyticsService : IPaymentAnalyticsService +{ + private readonly IPaymentRepository _paymentRepository; + private readonly IDistributedCache _distributedCache; + private readonly ILogger _logger; + + public async Task GetPaymentAnalyticsAsync( + CustomerId customerId, + DateOnly date, + CancellationToken cancellationToken = default) + { + var cacheKey = $"analytics:payments:{customerId}:{date:yyyy-MM-dd}"; + + var cachedAnalytics = await GetFromCacheAsync(cacheKey, cancellationToken); + if (cachedAnalytics is not null) + { + return cachedAnalytics; + } + + var analytics = await CalculatePaymentAnalyticsAsync(customerId, date, cancellationToken); + + // Cache for 1 hour, but longer for older dates (they won't change) + var expiry = date == DateOnly.FromDateTime(DateTime.UtcNow) + ? TimeSpan.FromHours(1) + : TimeSpan.FromDays(1); + + await SetCacheAsync(cacheKey, analytics, expiry, cancellationToken); + + return analytics; + } + + private async Task GetFromCacheAsync(string cacheKey, CancellationToken cancellationToken) + where T : class + { + try + { + var cachedValue = await _distributedCache.GetStringAsync(cacheKey, cancellationToken); + return string.IsNullOrEmpty(cachedValue) + ? null + : JsonSerializer.Deserialize(cachedValue); + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Failed to get value from cache for key {CacheKey}", cacheKey); + return null; + } + } + + private async Task SetCacheAsync(string cacheKey, T value, TimeSpan expiry, CancellationToken cancellationToken) + { + try + { + var serializedValue = JsonSerializer.Serialize(value); + var options = new DistributedCacheEntryOptions + { + AbsoluteExpirationRelativeToNow = expiry + }; + + await _distributedCache.SetStringAsync(cacheKey, serializedValue, options, cancellationToken); + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Failed to set cache for key {CacheKey}", cacheKey); + } + } +} +``` + +## Security Best Practices + +### Input Validation and Sanitization + +```csharp +// Good - Comprehensive input validation using FluentValidation +public class CreateCustomerRequestValidator : AbstractValidator +{ + public CreateCustomerRequestValidator() + { + RuleFor(x => x.Email) + .NotEmpty() + .EmailAddress() + .MaximumLength(320) + .WithMessage("Email must be a valid email address with maximum 320 characters"); + + RuleFor(x => x.FirstName) + .NotEmpty() + .MaximumLength(100) + .Matches(@"^[a-zA-Z\s\-'\.]+$") + .WithMessage("First name can only contain letters, spaces, hyphens, apostrophes, and periods"); + + RuleFor(x => x.LastName) + .NotEmpty() + .MaximumLength(100) + .Matches(@"^[a-zA-Z\s\-'\.]+$") + .WithMessage("Last name can only contain letters, spaces, hyphens, apostrophes, and periods"); + + RuleFor(x => x.PhoneNumber) + .Matches(@"^\+?[1-9]\d{1,14}$") + .When(x => !string.IsNullOrEmpty(x.PhoneNumber)) + .WithMessage("Phone number must be in international format"); + + RuleFor(x => x.DateOfBirth) + .LessThan(DateTime.UtcNow.AddYears(-18)) + .GreaterThan(DateTime.UtcNow.AddYears(-120)) + .WithMessage("Customer must be between 18 and 120 years old"); + } +} + +// Good - SQL injection prevention with parameterized queries +public class PaymentRepository : IPaymentRepository +{ + private readonly PaymentDbContext _context; + + // Entity Framework automatically parameterizes queries + public async Task> SearchPaymentsAsync( + string? cardNumberLast4, + string? customerEmail, + CancellationToken cancellationToken = default) + { + var query = _context.Payments.AsQueryable(); + + if (!string.IsNullOrEmpty(cardNumberLast4)) + { + // EF Core automatically parameterizes this + query = query.Where(p => p.CardNumber.EndsWith(cardNumberLast4)); + } + + if (!string.IsNullOrEmpty(customerEmail)) + { + query = query.Where(p => p.Customer.Email == customerEmail); + } + + return await query.ToListAsync(cancellationToken); + } + + // When using raw SQL, always use parameters + public async Task GetTotalRevenueAsync(DateTime startDate, DateTime endDate, CancellationToken cancellationToken = default) + { + return await _context.Database + .SqlQuery($"SELECT SUM(amount) FROM payments WHERE created_at BETWEEN {startDate} AND {endDate} AND status = 'Completed'") + .FirstOrDefaultAsync(cancellationToken); + } +} + +// Good - XSS prevention with proper encoding +public class PaymentReportService : IPaymentReportService +{ + public async Task GenerateHtmlReportAsync(IReadOnlyList payments) + { + var html = new StringBuilder(); + html.AppendLine(""); + html.AppendLine("

Payment Report

"); + html.AppendLine(""); + html.AppendLine(""); + + foreach (var payment in payments) + { + html.AppendLine(""); + html.AppendLine($""); + html.AppendLine($""); + html.AppendLine($""); + html.AppendLine($""); + html.AppendLine(""); + } + + html.AppendLine("
IDAmountCustomerStatus
{HtmlEncoder.Default.Encode(payment.Id.ToString())}{HtmlEncoder.Default.Encode(payment.Amount.ToString("C"))}{HtmlEncoder.Default.Encode(payment.Customer.Email)}{HtmlEncoder.Default.Encode(payment.Status.ToString())}
"); + html.AppendLine(""); + + return html.ToString(); + } +} +``` + +### Authentication and Authorization + +```csharp +// Good - JWT authentication configuration +public static class AuthenticationExtensions +{ + public static IServiceCollection AddJwtAuthentication( + this IServiceCollection services, + IConfiguration configuration) + { + var jwtSettings = configuration.GetSection("Jwt").Get() + ?? throw new InvalidOperationException("JWT settings not found"); + + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddJwtBearer(options => + { + options.TokenValidationParameters = new TokenValidationParameters + { + ValidateIssuer = true, + ValidateAudience = true, + ValidateLifetime = true, + ValidateIssuerSigningKey = true, + ValidIssuer = jwtSettings.Issuer, + ValidAudience = jwtSettings.Audience, + IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.SecretKey)), + ClockSkew = TimeSpan.FromMinutes(5) + }; + + options.Events = new JwtBearerEvents + { + OnAuthenticationFailed = context => + { + var logger = context.HttpContext.RequestServices.GetRequiredService>(); + logger.LogWarning("Authentication failed: {Error}", context.Exception.Message); + return Task.CompletedTask; + }, + OnTokenValidated = context => + { + var logger = context.HttpContext.RequestServices.GetRequiredService>(); + logger.LogDebug("Token validated for user: {UserId}", context.Principal?.Identity?.Name); + return Task.CompletedTask; + } + }; + }); + + return services; + } +} + +// Good - Custom authorization policies +public static class AuthorizationExtensions +{ + public static IServiceCollection AddCustomAuthorization(this IServiceCollection services) + { + services.AddAuthorization(options => + { + options.AddPolicy("RequireAdminRole", policy => + policy.RequireRole("Admin")); + + options.AddPolicy("RequireManagerOrAdmin", policy => + policy.RequireRole("Manager", "Admin")); + + options.AddPolicy("RequirePaymentAccess", policy => + policy.RequireAssertion(context => + context.User.HasClaim("permission", "payments:read") || + context.User.IsInRole("Admin"))); + + options.AddPolicy("RequireResourceOwnership", policy => + policy.Requirements.Add(new ResourceOwnershipRequirement())); + }); + + services.AddScoped(); + return services; + } +} + +public class ResourceOwnershipRequirement : IAuthorizationRequirement { } + +public class ResourceOwnershipHandler : AuthorizationHandler +{ + private readonly IHttpContextAccessor _httpContextAccessor; + + public ResourceOwnershipHandler(IHttpContextAccessor httpContextAccessor) + { + _httpContextAccessor = httpContextAccessor; + } + + protected override Task HandleRequirementAsync( + AuthorizationHandlerContext context, + ResourceOwnershipRequirement requirement) + { + var httpContext = _httpContextAccessor.HttpContext; + if (httpContext is null) + { + context.Fail(); + return Task.CompletedTask; + } + + var userIdClaim = context.User.FindFirst("sub")?.Value; + var resourceUserId = httpContext.Request.RouteValues["userId"]?.ToString(); + + if (userIdClaim == resourceUserId || context.User.IsInRole("Admin")) + { + context.Succeed(requirement); + } + else + { + context.Fail(); + } + + return Task.CompletedTask; + } +} + +// Good - Secure controller with proper authorization +[ApiController] +[Route("api/[controller]")] +[Authorize] +public class PaymentsController : ControllerBase +{ + [HttpGet] + [Authorize(Policy = "RequirePaymentAccess")] + public async Task>> GetPayments( + [FromQuery] GetPaymentsRequest request, + CancellationToken cancellationToken = default) + { + // Implementation... + } + + [HttpGet("{id:guid}")] + [Authorize(Policy = "RequireResourceOwnership")] + public async Task> GetPayment( + [FromRoute] Guid id, + CancellationToken cancellationToken = default) + { + // Implementation... + } + + [HttpPost] + [Authorize(Roles = "User,Manager,Admin")] + public async Task> CreatePayment( + [FromBody] CreatePaymentRequest request, + CancellationToken cancellationToken = default) + { + // Implementation... + } + + [HttpDelete("{id:guid}")] + [Authorize(Roles = "Admin")] + public async Task DeletePayment( + [FromRoute] Guid id, + CancellationToken cancellationToken = default) + { + // Implementation... + } +} +``` + +### Sensitive Data Protection + +```csharp +// Good - Data encryption for sensitive information +public class EncryptionService : IEncryptionService +{ + private readonly byte[] _key; + private readonly byte[] _iv; + + public EncryptionService(IOptions options) + { + var encryptionOptions = options.Value; + _key = Convert.FromBase64String(encryptionOptions.Key); + _iv = Convert.FromBase64String(encryptionOptions.IV); + } + + public string EncryptString(string plainText) + { + if (string.IsNullOrEmpty(plainText)) + return plainText; + + using var aes = Aes.Create(); + aes.Key = _key; + aes.IV = _iv; + + var encryptor = aes.CreateEncryptor(); + using var msEncrypt = new MemoryStream(); + using var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write); + using var swEncrypt = new StreamWriter(csEncrypt); + + swEncrypt.Write(plainText); + + return Convert.ToBase64String(msEncrypt.ToArray()); + } + + public string DecryptString(string cipherText) + { + if (string.IsNullOrEmpty(cipherText)) + return cipherText; + + using var aes = Aes.Create(); + aes.Key = _key; + aes.IV = _iv; + + var decryptor = aes.CreateDecryptor(); + using var msDecrypt = new MemoryStream(Convert.FromBase64String(cipherText)); + using var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read); + using var srDecrypt = new StreamReader(csDecrypt); + + return srDecrypt.ReadToEnd(); + } +} + +// Good - Secure logging that doesn't expose sensitive data +public static partial class LoggerExtensions +{ + [LoggerMessage(EventId = 1001, Level = LogLevel.Information, Message = "Payment {PaymentId} created for customer {CustomerId} with amount {Amount:C}")] + public static partial void LogPaymentCreated(this ILogger logger, PaymentId paymentId, CustomerId customerId, decimal amount); + + [LoggerMessage(EventId = 1002, Level = LogLevel.Warning, Message = "Payment {PaymentId} failed validation: {ValidationErrors}")] + public static partial void LogPaymentValidationFailed(this ILogger logger, PaymentId paymentId, string validationErrors); + + [LoggerMessage(EventId = 1003, Level = LogLevel.Error, Message = "Payment processing failed for payment {PaymentId}")] + public static partial void LogPaymentProcessingFailed(this ILogger logger, PaymentId paymentId, Exception exception); + + // Never log sensitive data like card numbers, CVV, etc. + public static void LogPaymentAttempt(this ILogger logger, PaymentRequest request) + { + // Only log non-sensitive data + logger.LogInformation( + "Payment attempt: Amount {Amount:C}, Currency {Currency}, Customer {CustomerId}, Card ending {CardLast4}", + request.Amount, + request.Currency, + request.CustomerId, + request.CardNumber?.Length >= 4 ? request.CardNumber[^4..] : "****"); + } +} + +// Good - Secure password hashing +public class PasswordService : IPasswordService +{ + private const int SaltSize = 32; + private const int HashSize = 32; + private const int Iterations = 100000; + + public string HashPassword(string password) + { + using var rng = RandomNumberGenerator.Create(); + var salt = new byte[SaltSize]; + rng.GetBytes(salt); + + using var pbkdf2 = new Rfc2898DeriveBytes(password, salt, Iterations, HashAlgorithmName.SHA256); + var hash = pbkdf2.GetBytes(HashSize); + + var hashBytes = new byte[SaltSize + HashSize]; + Array.Copy(salt, 0, hashBytes, 0, SaltSize); + Array.Copy(hash, 0, hashBytes, SaltSize, HashSize); + + return Convert.ToBase64String(hashBytes); + } + + public bool VerifyPassword(string password, string hashedPassword) + { + var hashBytes = Convert.FromBase64String(hashedPassword); + var salt = new byte[SaltSize]; + Array.Copy(hashBytes, 0, salt, 0, SaltSize); + + using var pbkdf2 = new Rfc2898DeriveBytes(password, salt, Iterations, HashAlgorithmName.SHA256); + var hash = pbkdf2.GetBytes(HashSize); + + for (var i = 0; i < HashSize; i++) + { + if (hashBytes[i + SaltSize] != hash[i]) + return false; + } + + return true; + } +} +``` + +## Monitoring and Observability + +IT IS VITAL THAT YOU ensure that you don't write any information to log files, or as trace attributes, that would be considered personal identifiable information or sensitive information. That explicatally covers things like names, email address, credit card information, social security or national insurance numbers. + +### Structured Logging + +```csharp +// Good - Structured logging with correlation IDs and context +public class PaymentService : IPaymentService +{ + private readonly IPaymentRepository _paymentRepository; + private readonly ILogger _logger; + + public async Task> ProcessPaymentAsync( + PaymentRequest request, + CancellationToken cancellationToken = default) + { + using var scope = _logger.BeginScope(new Dictionary + { + ["PaymentId"] = PaymentId.New(), + ["CustomerId"] = request.CustomerId, + ["Amount"] = request.Amount, + ["Currency"] = request.Currency + }); + + _logger.LogInformation("Starting payment processing"); + + try + { + var validationResult = await ValidatePaymentAsync(request, cancellationToken); + if (!validationResult.IsValid) + { + _logger.LogWarning("Payment validation failed: {ValidationErrors}", + string.Join(", ", validationResult.Errors)); + return Result.Failure("Validation failed"); + } + + var payment = await CreatePaymentAsync(request, cancellationToken); + + _logger.LogInformation("Payment {PaymentId} processed successfully", payment.Id); + return Result.Success(payment); + } + catch (Exception ex) + { + _logger.LogError(ex, "Payment processing failed"); + return Result.Failure("Payment processing failed"); + } + } +} + +// Good - Activity and tracing for distributed systems +public class PaymentGatewayService : IPaymentGatewayService +{ + private static readonly ActivitySource ActivitySource = new("PaymentGateway"); + private readonly HttpClient _httpClient; + private readonly ILogger _logger; + + public async Task AuthorizePaymentAsync( + AuthorizationRequest request, + CancellationToken cancellationToken = default) + { + using var activity = ActivitySource.StartActivity("payment.authorize"); + activity?.SetTag("payment.amount", request.Amount.ToString()); + activity?.SetTag("payment.currency", request.Currency); + activity?.SetTag("customer.id", request.CustomerId.ToString()); + + try + { + var httpRequest = new HttpRequestMessage(HttpMethod.Post, "/authorize") + { + Content = JsonContent.Create(request) + }; + + var response = await _httpClient.SendAsync(httpRequest, cancellationToken); + + activity?.SetTag("http.status_code", (int)response.StatusCode); + + if (response.IsSuccessStatusCode) + { + var result = await response.Content.ReadFromJsonAsync(cancellationToken: cancellationToken); + activity?.SetTag("authorization.result", "success"); + return result!; + } + + activity?.SetTag("authorization.result", "failed"); + activity?.SetStatus(ActivityStatusCode.Error, "Authorization failed"); + + return AuthorizationResult.Failed("Gateway authorization failed"); + } + catch (Exception ex) + { + activity?.SetStatus(ActivityStatusCode.Error, ex.Message); + _logger.LogError(ex, "Payment authorization failed"); + throw; + } + } +} +``` + +### Health Checks + +```csharp +// Good - Comprehensive health checks +public static class HealthCheckExtensions +{ + public static IServiceCollection AddCustomHealthChecks( + this IServiceCollection services, + IConfiguration configuration) + { + services.AddHealthChecks() + .AddDbContextCheck("database") + .AddRedis(configuration.GetConnectionString("Redis")!, "redis") + .AddRabbitMQ(rabbitConnectionString: configuration.GetConnectionString("RabbitMQ")!, name: "rabbitmq") + .AddUrlGroup(new Uri($"{configuration["PaymentGateway:BaseUrl"]}/health"), "payment-gateway") + .AddCheck("payment-service") + .AddCheck("filesystem"); + + return services; + } +} + +public class PaymentServiceHealthCheck : IHealthCheck +{ + private readonly IPaymentRepository _paymentRepository; + private readonly ILogger _logger; + + public PaymentServiceHealthCheck( + IPaymentRepository paymentRepository, + ILogger logger) + { + _paymentRepository = paymentRepository; + _logger = logger; + } + + public async Task CheckHealthAsync( + HealthCheckContext context, + CancellationToken cancellationToken = default) + { + try + { + // Test database connectivity by checking if we can count payments + var canConnectToDatabase = await TestDatabaseConnectionAsync(cancellationToken); + if (!canConnectToDatabase) + { + return HealthCheckResult.Unhealthy("Cannot connect to payment database"); + } + + // Test critical business functionality + var canProcessPayments = await TestPaymentProcessingAsync(cancellationToken); + if (!canProcessPayments) + { + return HealthCheckResult.Degraded("Payment processing may be impaired"); + } + + return HealthCheckResult.Healthy("Payment service is healthy"); + } + catch (Exception ex) + { + _logger.LogError(ex, "Health check failed"); + return HealthCheckResult.Unhealthy("Payment service health check failed", ex); + } + } + + private async Task TestDatabaseConnectionAsync(CancellationToken cancellationToken) + { + try + { + // Simple query to test database connectivity + var recentPayments = await _paymentRepository.GetPagedAsync(1, 1, cancellationToken: cancellationToken); + return true; + } + catch + { + return false; + } + } + + private async Task TestPaymentProcessingAsync(CancellationToken cancellationToken) + { + try + { + // Test payment validation logic without hitting external services + var testRequest = new PaymentRequestBuilder() + .WithAmount(100m) + .WithCurrency("GBP") + .Build(); + + var validator = new PaymentRequestValidator(); + var validationResult = await validator.ValidateAsync(testRequest, cancellationToken); + + return validationResult.IsValid; + } + catch + { + return false; + } + } +} + +public class FileSystemHealthCheck : IHealthCheck +{ + private readonly IWebHostEnvironment _environment; + + public FileSystemHealthCheck(IWebHostEnvironment environment) + { + _environment = environment; + } + + public Task CheckHealthAsync( + HealthCheckContext context, + CancellationToken cancellationToken = default) + { + try + { + var tempPath = Path.Combine(_environment.ContentRootPath, "temp"); + + // Ensure temp directory exists + Directory.CreateDirectory(tempPath); + + // Test write permissions + var testFile = Path.Combine(tempPath, $"healthcheck_{Guid.NewGuid()}.tmp"); + File.WriteAllText(testFile, "health check test"); + + // Test read permissions + var content = File.ReadAllText(testFile); + + // Cleanup + File.Delete(testFile); + + return Task.FromResult(HealthCheckResult.Healthy("File system is accessible")); + } + catch (Exception ex) + { + return Task.FromResult(HealthCheckResult.Unhealthy("File system access failed", ex)); + } + } +} + +// Register health checks in Program.cs +app.MapHealthChecks("/health", new HealthCheckOptions +{ + ResponseWriter = async (context, report) => + { + context.Response.ContentType = "application/json"; + + var result = JsonSerializer.Serialize(new + { + status = report.Status.ToString(), + checks = report.Entries.Select(e => new + { + name = e.Key, + status = e.Value.Status.ToString(), + exception = e.Value.Exception?.Message, + duration = e.Value.Duration.ToString() + }) + }); + + await context.Response.WriteAsync(result); + } +}); + +app.MapHealthChecks("/health/ready", new HealthCheckOptions +{ + Predicate = check => check.Tags.Contains("ready") +}); + +app.MapHealthChecks("/health/live", new HealthCheckOptions +{ + Predicate = _ => false +}); +``` + +### Metrics and Telemetry + +```csharp +// Good - Custom metrics for business operations +public class PaymentMetrics +{ + private readonly Counter _paymentsProcessed; + private readonly Counter _paymentsFailed; + private readonly Histogram _paymentProcessingTime; + private readonly Histogram _paymentAmount; + + public PaymentMetrics(IMeterFactory meterFactory) + { + var meter = meterFactory.Create("PaymentService"); + + _paymentsProcessed = meter.CreateCounter( + "payments_processed_total", + "Total number of payments processed"); + + _paymentsFailed = meter.CreateCounter( + "payments_failed_total", + "Total number of failed payments"); + + _paymentProcessingTime = meter.CreateHistogram( + "payment_processing_duration_seconds", + "Payment processing duration in seconds"); + + _paymentAmount = meter.CreateHistogram( + "payment_amount", + "Payment amounts"); + } + + public void RecordPaymentProcessed(string currency, string status, double processingTimeSeconds, double amount) + { + _paymentsProcessed.Add(1, new KeyValuePair("currency", currency), + new KeyValuePair("status", status)); + _paymentProcessingTime.Record(processingTimeSeconds); + _paymentAmount.Record(amount, new KeyValuePair("currency", currency)); + } + + public void RecordPaymentFailed(string currency, string errorType) + { + _paymentsFailed.Add(1, new KeyValuePair("currency", currency), + new KeyValuePair("error_type", errorType)); + } +} + +public class PaymentService : IPaymentService +{ + private readonly PaymentMetrics _metrics; + private readonly ILogger _logger; + + public async Task> ProcessPaymentAsync( + PaymentRequest request, + CancellationToken cancellationToken = default) + { + var stopwatch = Stopwatch.StartNew(); + + try + { + var payment = await ProcessPaymentInternalAsync(request, cancellationToken); + + stopwatch.Stop(); + _metrics.RecordPaymentProcessed( + request.Currency, + "success", + stopwatch.Elapsed.TotalSeconds, + (double)request.Amount); + + return Result.Success(payment); + } + catch (Exception ex) + { + stopwatch.Stop(); + _metrics.RecordPaymentFailed(request.Currency, ex.GetType().Name); + + _logger.LogError(ex, "Payment processing failed"); + return Result.Failure("Payment processing failed"); + } + } +} +``` \ No newline at end of file diff --git a/src/order-service/src/Orders.Api/CompleteOrder/CompleteOrderHandler.cs b/src/order-service/src/Orders.Api/CompleteOrder/CompleteOrderHandler.cs index f2bba942..07954ccd 100644 --- a/src/order-service/src/Orders.Api/CompleteOrder/CompleteOrderHandler.cs +++ b/src/order-service/src/Orders.Api/CompleteOrder/CompleteOrderHandler.cs @@ -3,8 +3,10 @@ // Copyright 2025 Datadog, Inc. using Microsoft.AspNetCore.Authorization; -using Orders.Api.CreateOrder; +using Orders.Api.Models; using Orders.Core; +using Orders.Core.Domain.Exceptions; +using FluentValidation; namespace Orders.Api.CompleteOrder; @@ -16,40 +18,122 @@ public static async Task Handle( CompleteOrderRequest request, IOrders orders, IEventGateway eventGateway, - ILogger logger) + IValidator validator, + ILogger logger) { + var correlationId = context.Items["CorrelationId"]?.ToString() ?? Guid.NewGuid().ToString(); + try { request.AddToTelemetry(); + // Validate request using FluentValidation + var validationResult = await validator.ValidateAsync(request); + if (!validationResult.IsValid) + { + var errors = validationResult.Errors + .GroupBy(e => e.PropertyName) + .ToDictionary(g => g.Key, g => g.Select(e => e.ErrorMessage).ToArray()); + + return Results.BadRequest(new ValidationErrorResponse( + ErrorCodes.ValidationError, + errors, + correlationId)); + } + var user = context.User.Claims.ExtractUserId(); + // Validate authorization if (user.UserType != "ADMIN") { - return Results.Unauthorized(); + logger.LogWarning("Unauthorized order completion attempt by user {UserId} with type {UserType}", + user.UserId, user.UserType); + + return Results.Problem( + detail: "Only administrators can complete orders", + title: "Forbidden", + statusCode: 403, + extensions: new Dictionary + { + ["correlationId"] = correlationId, + ["errorCode"] = ErrorCodes.Forbidden + }); } var existingOrder = await orders.WithOrderId(request.UserId, request.OrderId); if (existingOrder == null) { - return Results.NotFound(); + logger.LogWarning("Order {OrderId} not found for user {UserId}", + request.OrderId, request.UserId); + + return Results.Problem( + detail: $"Order with ID '{request.OrderId}' not found for user '{request.UserId}'", + title: "Order Not Found", + statusCode: 404, + extensions: new Dictionary + { + ["correlationId"] = correlationId, + ["errorCode"] = ErrorCodes.NotFound + }); } existingOrder.CompleteOrder(); await orders.Store(existingOrder); await eventGateway.HandleOrderCompleted(existingOrder); + logger.LogInformation("Order {OrderId} completed successfully by admin {AdminUserId}", + existingOrder.OrderNumber, user.UserId); + return Results.Ok(new OrderDTO(existingOrder)); } - catch (OrderNotConfirmedException) + catch (Orders.Core.Domain.Exceptions.OrderNotConfirmedException ex) { - return Results.BadRequest(""); + logger.LogWarning(ex, "Attempted to complete unconfirmed order {OrderId}", request.OrderId); + + return Results.Conflict(new ErrorResponse( + ErrorCodes.InvalidState, + "Order must be confirmed before it can be completed", + "Only confirmed orders can be marked as complete", + null, + correlationId)); } - catch (Exception e) + catch (InvalidOrderStateException ex) { - logger.LogError(e, "Error retrieving order"); - return Results.InternalServerError(); + logger.LogWarning(ex, "Invalid order state transition for order {OrderId}", request.OrderId); + + return Results.Conflict(new ErrorResponse( + ErrorCodes.InvalidState, + "Order state transition not allowed", + ex.Message, + null, + correlationId)); + } + catch (ArgumentException ex) + { + logger.LogWarning(ex, "Invalid argument provided for order completion"); + + return Results.BadRequest(new ErrorResponse( + ErrorCodes.ValidationError, + "Invalid input provided", + ex.Message, + null, + correlationId)); + } + catch (Exception ex) + { + logger.LogError(ex, "Unexpected error completing order {OrderId} for user {UserId}", + request.OrderId, request.UserId); + + return Results.Problem( + detail: "An unexpected error occurred while completing the order", + title: "Internal Server Error", + statusCode: 500, + extensions: new Dictionary + { + ["correlationId"] = correlationId, + ["errorCode"] = ErrorCodes.InternalError + }); } } } \ No newline at end of file diff --git a/src/order-service/src/Orders.Api/CompleteOrder/CompleteOrderRequest.cs b/src/order-service/src/Orders.Api/CompleteOrder/CompleteOrderRequest.cs deleted file mode 100644 index 326fd588..00000000 --- a/src/order-service/src/Orders.Api/CompleteOrder/CompleteOrderRequest.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2025 Datadog, Inc. - -using System.Text.Json.Serialization; - -namespace Orders.Api.CompleteOrder; - -public record CompleteOrderRequest -{ - [JsonPropertyName("orderId")] public string OrderId { get; set; } = ""; - - [JsonPropertyName("userId")] - public string UserId { get; set; } = ""; -} \ No newline at end of file diff --git a/src/order-service/src/Orders.Api/ConfirmedOrders/ConfirmedOrdersHandler.cs b/src/order-service/src/Orders.Api/ConfirmedOrders/ConfirmedOrdersHandler.cs index dbdf7e5f..42cec93c 100644 --- a/src/order-service/src/Orders.Api/ConfirmedOrders/ConfirmedOrdersHandler.cs +++ b/src/order-service/src/Orders.Api/ConfirmedOrders/ConfirmedOrdersHandler.cs @@ -3,9 +3,11 @@ // Copyright 2025 Datadog, Inc. using Microsoft.AspNetCore.Authorization; -using Orders.Api.CompleteOrder; -using Orders.Api.CreateOrder; +using Microsoft.AspNetCore.Mvc; +using Orders.Api.Models; using Orders.Core; +using Orders.Core.Common; +using FluentValidation; namespace Orders.Api.ConfirmedOrders; @@ -16,29 +18,93 @@ public static async Task Handle( HttpContext context, IOrders orders, IEventGateway eventGateway, - ILogger logger) + IValidator validator, + ILogger logger, + [FromQuery] int pageSize = 20, + [FromQuery] string? pageToken = null, + CancellationToken cancellationToken = default) { + var correlationId = context.Items["CorrelationId"]?.ToString() ?? Guid.NewGuid().ToString(); + try { - var user = context.User.Claims.ExtractUserId(); + // Create request object for validation + var paginationRequest = new PaginationQueryRequest + { + PageSize = pageSize, + PageToken = pageToken + }; + + // Validate using FluentValidation + var validationResult = await validator.ValidateAsync(paginationRequest, cancellationToken); + if (!validationResult.IsValid) + { + var errors = validationResult.Errors + .GroupBy(e => e.PropertyName) + .ToDictionary(g => g.Key, g => g.Select(e => e.ErrorMessage).ToArray()); + + return Results.BadRequest(new ValidationErrorResponse( + ErrorCodes.ValidationError, + errors, + correlationId)); + } - if (user.UserType != "ADMIN") + var user = context.User.Claims.ExtractUserId(); + if (user?.UserType != "ADMIN") { - return Results.Unauthorized(); + logger.LogWarning("Unauthorized access attempt to confirmed orders by user {UserId} with type {UserType}", + user?.UserId, user?.UserType); + + return Results.Problem( + detail: "Only administrators can access confirmed orders", + title: "Forbidden", + statusCode: 403, + extensions: new Dictionary + { + ["correlationId"] = correlationId, + ["errorCode"] = ErrorCodes.Forbidden + }); } - var confirmedOrders = await orders.ConfirmedOrders(); + var pagination = new PaginationRequest(pageSize, pageToken); + var pagedResult = await orders.ConfirmedOrders(pagination, cancellationToken); + + var response = new + { + Items = pagedResult.Items.Select(order => new OrderDTO(order)), + PageSize = pagedResult.PageSize, + HasMorePages = pagedResult.HasMorePages, + NextPageToken = pagedResult.NextPageToken + }; + + logger.LogDebug("Retrieved {ItemCount} confirmed orders", pagedResult.ItemCount); - return Results.Ok(confirmedOrders.Select(order => new OrderDTO(order))); + return Results.Ok(response); } - catch (OrderNotConfirmedException) + catch (ArgumentException ex) { - return Results.BadRequest(""); + logger.LogWarning(ex, "Invalid argument provided for confirmed orders retrieval"); + + return Results.BadRequest(new ErrorResponse( + ErrorCodes.ValidationError, + "Invalid request parameters", + ex.Message, + null, + correlationId)); } - catch (Exception e) + catch (Exception ex) { - logger.LogError(e, "Error retrieving order"); - return Results.InternalServerError(); + logger.LogError(ex, "Unexpected error retrieving confirmed orders"); + + return Results.Problem( + detail: "An unexpected error occurred while retrieving confirmed orders", + title: "Internal Server Error", + statusCode: 500, + extensions: new Dictionary + { + ["correlationId"] = correlationId, + ["errorCode"] = ErrorCodes.InternalError + }); } } } \ No newline at end of file diff --git a/src/order-service/src/Orders.Api/CreateOrder/CreateOrderHandler.cs b/src/order-service/src/Orders.Api/CreateOrder/CreateOrderHandler.cs index 5763131c..14fbf77e 100644 --- a/src/order-service/src/Orders.Api/CreateOrder/CreateOrderHandler.cs +++ b/src/order-service/src/Orders.Api/CreateOrder/CreateOrderHandler.cs @@ -3,7 +3,12 @@ // Copyright 2025 Datadog, Inc. using Microsoft.AspNetCore.Authorization; +using Orders.Api.Models; using Orders.Core; +using Orders.Core.Domain.Exceptions; +using FluentValidation; +using Orders.Api.Logging; +using System.Diagnostics; namespace Orders.Api.CreateOrder; @@ -15,34 +20,150 @@ public static async Task Handle( CreateOrderRequest request, IOrders orders, IOrderWorkflow orderWorkflow, + IValidator validator, ILogger logger) { + var correlationId = context.Items["CorrelationId"]?.ToString() ?? Guid.NewGuid().ToString(); + var stopwatch = Stopwatch.StartNew(); + + using var performanceScope = logger.BeginPerformanceScope("CreateOrder", correlationId); + try { request.AddToTelemetry(); var userClaims = context.User.Claims.ExtractUserId(); + var userType = userClaims?.UserType ?? "Unknown"; + + // Log operation start with safe context + logger.LogOrderCreationStarted(request.Products.Length, userType); + + // Validate request using FluentValidation + var validationStartTime = Stopwatch.GetTimestamp(); + var validationResult = await validator.ValidateAsync(request); + var validationDuration = Stopwatch.GetElapsedTime(validationStartTime); + + if (!validationResult.IsValid) + { + var errors = validationResult.Errors + .GroupBy(e => e.PropertyName) + .ToDictionary(g => g.Key, g => g.Select(e => e.ErrorMessage).ToArray()); + + logger.LogOrderCreationValidationFailed(validationResult.Errors.Count); + logger.LogValidationFailed(validationResult.Errors.Count, "CreateOrder"); + + return Results.BadRequest(new ValidationErrorResponse( + ErrorCodes.ValidationError, + errors, + correlationId)); + } + + logger.LogValidationPassed("CreateOrder", (long)validationDuration.TotalMilliseconds); Order? newOrder = null; + string orderType; if (userClaims.UserType == "PREMIUM") { newOrder = Order.CreatePriorityOrder(userClaims.UserId, request.Products); + orderType = "Priority"; } else { newOrder = Order.CreateStandardOrder(userClaims.UserId, request.Products); + orderType = "Standard"; } + // Log workflow start + logger.LogWorkflowStarted("OrderCreation", orderType); + await orders.Store(newOrder); await orderWorkflow.StartWorkflowFor(newOrder); - return Results.Ok(new OrderDTO(newOrder)); + stopwatch.Stop(); + + // Log successful completion with structured context + logger.LogOrderCreated(orderType, stopwatch.ElapsedMilliseconds); + + // Log business metrics (NO PII) + var businessContext = new BusinessMetricsContext + { + CorrelationId = correlationId, + EventType = "OrderCreated", + OrderType = orderType, + UserTier = userType, + ProductCount = request.Products.Length, + Timestamp = DateTime.UtcNow, + ProcessingStage = "Created" + }; + logger.LogBusinessMetrics("Order creation completed", businessContext); + + return Results.Created($"/api/orders/{newOrder.OrderNumber}", new OrderDTO(newOrder)); } - catch (Exception e) + catch (OrderValidationException ex) { - logger.LogError(e, "Error creating order"); - return Results.InternalServerError(); + var userType = context.User.Claims.ExtractUserId()?.UserType ?? "Unknown"; + logger.LogOrderCreationValidationFailed(ex.ValidationErrors.Count); + + return Results.BadRequest(new ValidationErrorResponse( + ErrorCodes.ValidationError, + ex.ValidationErrors, + correlationId)); + } + catch (InvalidOrderStateException ex) + { + var userType = context.User.Claims.ExtractUserId()?.UserType ?? "Unknown"; + logger.LogOrderCreationFailed(userType, ex); + + return Results.Conflict(new ErrorResponse( + ErrorCodes.InvalidState, + "Order state transition not allowed", + ex.Message, + null, + correlationId)); + } + catch (WorkflowException ex) + { + var userType = context.User.Claims.ExtractUserId()?.UserType ?? "Unknown"; + logger.LogWorkflowFailed("OrderCreation", "Unknown", ex); + logger.LogOrderCreationFailed(userType, ex); + + return Results.Problem( + detail: "Order workflow could not be started", + title: "Workflow Error", + statusCode: 500, + extensions: new Dictionary + { + ["correlationId"] = correlationId, + ["errorCode"] = ErrorCodes.ServiceUnavailable + }); + } + catch (ArgumentException ex) + { + var userType = context.User.Claims.ExtractUserId()?.UserType ?? "Unknown"; + logger.LogValidationFailed(1, "CreateOrder"); + + return Results.BadRequest(new ErrorResponse( + ErrorCodes.ValidationError, + "Invalid input provided", + ex.Message, + null, + correlationId)); + } + catch (Exception ex) + { + var userType = context.User.Claims.ExtractUserId()?.UserType ?? "Unknown"; + logger.LogOrderCreationFailed(userType, ex); + + return Results.Problem( + detail: "An unexpected error occurred while creating the order", + title: "Internal Server Error", + statusCode: 500, + extensions: new Dictionary + { + ["correlationId"] = correlationId, + ["errorCode"] = ErrorCodes.InternalError + }); } } } \ No newline at end of file diff --git a/src/order-service/src/Orders.Api/GetOrderDetails/GetOrderDetailsHandler.cs b/src/order-service/src/Orders.Api/GetOrderDetails/GetOrderDetailsHandler.cs index 7267a3d1..9fcca946 100644 --- a/src/order-service/src/Orders.Api/GetOrderDetails/GetOrderDetailsHandler.cs +++ b/src/order-service/src/Orders.Api/GetOrderDetails/GetOrderDetailsHandler.cs @@ -3,30 +3,96 @@ // Copyright 2025 Datadog, Inc. using Microsoft.AspNetCore.Authorization; +using Orders.Api.Models; using Orders.Core; using Orders.Core.Adapters; +using FluentValidation; namespace Orders.Api.GetOrderDetails; public class GetOrderDetailsHandler { [Authorize] - public static async Task Handle(HttpContext context, string orderId, IOrders orders, ILogger logger) + public static async Task Handle( + HttpContext context, + string orderId, + IOrders orders, + IValidator validator, + ILogger logger) { + var correlationId = context.Items["CorrelationId"]?.ToString() ?? Guid.NewGuid().ToString(); + try { - orderId.AddToTelemetry("order.id"); - var user = context.User.Claims.ExtractUserId(); + + // Create request object for validation + var request = new GetOrderRequest + { + OrderId = orderId, + UserId = user.UserId + }; + + // Validate using FluentValidation + var validationResult = await validator.ValidateAsync(request); + if (!validationResult.IsValid) + { + var errors = validationResult.Errors + .GroupBy(e => e.PropertyName) + .ToDictionary(g => g.Key, g => g.Select(e => e.ErrorMessage).ToArray()); + + return Results.BadRequest(new ValidationErrorResponse( + ErrorCodes.ValidationError, + errors, + correlationId)); + } + + orderId.AddToTelemetry("order.id"); var existingOrder = await orders.WithOrderId(user.UserId, orderId); - if (existingOrder is null) return Results.NotFound(); + + if (existingOrder is null) + { + logger.LogWarning("Order {OrderId} not found for user {UserId}", orderId, user.UserId); + + return Results.Problem( + detail: $"Order with ID '{orderId}' not found", + title: "Order Not Found", + statusCode: 404, + extensions: new Dictionary + { + ["correlationId"] = correlationId, + ["errorCode"] = ErrorCodes.NotFound + }); + } + logger.LogDebug("Order {OrderId} retrieved successfully for user {UserId}", orderId, user.UserId); return Results.Ok(new OrderDTO(existingOrder)); } - catch (Exception e) + catch (ArgumentException ex) + { + logger.LogWarning(ex, "Invalid argument provided for order retrieval"); + + return Results.BadRequest(new ErrorResponse( + ErrorCodes.ValidationError, + "Invalid order ID format", + ex.Message, + null, + correlationId)); + } + catch (Exception ex) { - logger.LogError(e, "Error retrieving order item"); - return Results.InternalServerError(); + logger.LogError(ex, "Unexpected error retrieving order {OrderId} for user {UserId}", + orderId, context.User.Claims.ExtractUserId().UserId); + + return Results.Problem( + detail: "An unexpected error occurred while retrieving the order", + title: "Internal Server Error", + statusCode: 500, + extensions: new Dictionary + { + ["correlationId"] = correlationId, + ["errorCode"] = ErrorCodes.InternalError + }); } } } \ No newline at end of file diff --git a/src/order-service/src/Orders.Api/GetUserOrders/GetUserOrdersHandler.cs b/src/order-service/src/Orders.Api/GetUserOrders/GetUserOrdersHandler.cs index 520896ca..a75cb33f 100644 --- a/src/order-service/src/Orders.Api/GetUserOrders/GetUserOrdersHandler.cs +++ b/src/order-service/src/Orders.Api/GetUserOrders/GetUserOrdersHandler.cs @@ -3,26 +3,134 @@ // Copyright 2025 Datadog, Inc. using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Orders.Api.Models; using Orders.Core; +using Orders.Core.Common; +using FluentValidation; +using Orders.Api.Logging; +using System.Diagnostics; namespace Orders.Api.GetUserOrders; public class GetUserOrdersHandler { [Authorize] - public static async Task Handle(HttpContext context, IOrders orders, ILogger logger) + public static async Task Handle( + HttpContext context, + IOrders orders, + IValidator validator, + ILogger logger, + [FromQuery] int pageSize = 20, + [FromQuery] string? pageToken = null, + CancellationToken cancellationToken = default) { + var correlationId = context.Items["CorrelationId"]?.ToString() ?? Guid.NewGuid().ToString(); + var stopwatch = Stopwatch.StartNew(); + + using var performanceScope = logger.BeginPerformanceScope("GetUserOrders", correlationId); + try { + // Log pagination start + logger.LogPaginationStarted(pageSize, "GetUserOrders"); + + // Create request object for validation + var paginationRequest = new PaginationQueryRequest + { + PageSize = pageSize, + PageToken = pageToken + }; + + // Validate using FluentValidation + var validationResult = await validator.ValidateAsync(paginationRequest, cancellationToken); + if (!validationResult.IsValid) + { + var errors = validationResult.Errors + .GroupBy(e => e.PropertyName) + .ToDictionary(g => g.Key, g => g.Select(e => e.ErrorMessage).ToArray()); + + logger.LogPaginationValidationFailed(pageSize); + logger.LogValidationFailed(validationResult.Errors.Count, "GetUserOrders"); + + return Results.BadRequest(new ValidationErrorResponse( + ErrorCodes.ValidationError, + errors, + correlationId)); + } + var user = context.User.Claims.ExtractUserId(); - var orderList = await orders.ForUser(user.UserId); + if (user?.UserId == null) + { + logger.LogAuthenticationFailed(); + return Results.Problem( + detail: "User authentication information is missing", + title: "Authentication Error", + statusCode: 401, + extensions: new Dictionary + { + ["correlationId"] = correlationId, + ["errorCode"] = ErrorCodes.Unauthorized + }); + } + + var userType = user.UserType ?? "Unknown"; + logger.LogUserAuthenticated(userType); + + var pagination = new PaginationRequest(pageSize, pageToken); + var pagedResult = await orders.ForUser(user.UserId, pagination, cancellationToken); + + stopwatch.Stop(); - return Results.Ok(orderList.Select(order => new OrderDTO(order))); + var response = new + { + Items = pagedResult.Items.Select(order => new OrderDTO(order)), + PageSize = pagedResult.PageSize, + HasMorePages = pagedResult.HasMorePages, + NextPageToken = pagedResult.NextPageToken + }; + + // Log pagination completion with structured context + logger.LogPaginationCompleted(pagedResult.ItemCount, pagedResult.HasMorePages, stopwatch.ElapsedMilliseconds); + + // Log business metrics (NO PII) + var businessContext = new BusinessMetricsContext + { + CorrelationId = correlationId, + EventType = "OrdersRetrieved", + UserTier = userType, + Timestamp = DateTime.UtcNow, + ProcessingStage = "Retrieved" + }; + logger.LogBusinessMetrics("User orders retrieved", businessContext); + + return Results.Ok(response); + } + catch (ArgumentException ex) + { + logger.LogValidationFailed(1, "GetUserOrders"); + + return Results.BadRequest(new ErrorResponse( + ErrorCodes.ValidationError, + "Invalid request parameters", + ex.Message, + null, + correlationId)); } - catch (Exception e) + catch (Exception ex) { - logger.LogError(e, "Error retrieving order item"); - return Results.InternalServerError(); + var userType = context.User.Claims.ExtractUserId()?.UserType ?? "Unknown"; + logger.LogDatabaseOperationFailed("GetUserOrders", ex); + + return Results.Problem( + detail: "An unexpected error occurred while retrieving orders", + title: "Internal Server Error", + statusCode: 500, + extensions: new Dictionary + { + ["correlationId"] = correlationId, + ["errorCode"] = ErrorCodes.InternalError + }); } } } \ No newline at end of file diff --git a/src/order-service/src/Orders.Api/Health/ApplicationHealthCheck.cs b/src/order-service/src/Orders.Api/Health/ApplicationHealthCheck.cs new file mode 100644 index 00000000..d28da7aa --- /dev/null +++ b/src/order-service/src/Orders.Api/Health/ApplicationHealthCheck.cs @@ -0,0 +1,151 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Orders.Api.Logging; +using Orders.Core; +using FluentValidation; +using Orders.Api.Models; + +namespace Orders.Api.Health; + +/// +/// Health check for application-specific functionality and dependencies +/// +public class ApplicationHealthCheck : IHealthCheck +{ + private readonly IOrders _orders; + private readonly IValidator _validator; + private readonly ILogger _logger; + + public ApplicationHealthCheck( + IOrders orders, + IValidator validator, + ILogger logger) + { + _orders = orders ?? throw new ArgumentNullException(nameof(orders)); + _validator = validator ?? throw new ArgumentNullException(nameof(validator)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } + + public async Task CheckHealthAsync( + HealthCheckContext context, + CancellationToken cancellationToken = default) + { + var correlationId = Guid.NewGuid().ToString(); + var healthData = new Dictionary + { + ["CheckTimestamp"] = DateTime.UtcNow, + ["CorrelationId"] = correlationId + }; + + try + { + _logger.LogInformation("Starting application health check with correlation {CorrelationId}", correlationId); + + // Test validation system + var validationTestPassed = await TestValidationSystemAsync(healthData, cancellationToken); + if (!validationTestPassed) + { + return HealthCheckResult.Unhealthy("Validation system is not functioning correctly", data: healthData); + } + + // Test basic repository connectivity (without accessing actual data) + var repositoryTestPassed = await TestRepositoryConnectivityAsync(healthData, cancellationToken); + if (!repositoryTestPassed) + { + return HealthCheckResult.Degraded("Repository connectivity issues detected", data: healthData); + } + + healthData["AllTestsPassed"] = true; + _logger.LogHealthCheckPassed(); + + return HealthCheckResult.Healthy("All application components are functioning correctly", data: healthData); + } + catch (Exception ex) + { + _logger.LogHealthCheckFailed("Application", ex); + healthData["Exception"] = ex.Message; + return HealthCheckResult.Unhealthy("Application health check failed", ex, healthData); + } + } + + private async Task TestValidationSystemAsync(Dictionary healthData, CancellationToken cancellationToken) + { + try + { + // Test validation with a valid request + var validRequest = new CreateOrderRequest + { + Products = new[] { "test-product-1", "test-product-2" } + }; + + var validResult = await _validator.ValidateAsync(validRequest, cancellationToken); + + // Test validation with an invalid request + var invalidRequest = new CreateOrderRequest + { + Products = Array.Empty() // Should fail validation + }; + + var invalidResult = await _validator.ValidateAsync(invalidRequest, cancellationToken); + + var validationWorks = validResult.IsValid && !invalidResult.IsValid; + + healthData["ValidationTestPassed"] = validationWorks; + healthData["ValidRequestResult"] = validResult.IsValid; + healthData["InvalidRequestResult"] = invalidResult.IsValid; + healthData["InvalidRequestErrors"] = invalidResult.Errors.Count; + + if (!validationWorks) + { + _logger.LogWarning("Validation system test failed: valid={ValidResult}, invalid={InvalidResult}", + validResult.IsValid, invalidResult.IsValid); + } + + return validationWorks; + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Validation system test failed with exception"); + healthData["ValidationTestPassed"] = false; + healthData["ValidationTestError"] = ex.Message; + return false; + } + } + + private async Task TestRepositoryConnectivityAsync(Dictionary healthData, CancellationToken cancellationToken) + { + try + { + // Test pagination functionality with minimal data request + var pagination = new Orders.Core.Common.PaginationRequest(1, null); // Request only 1 item + + // Try to get orders for a test user (this tests basic connectivity without exposing real data) + var testUserId = "health-check-test-user-" + Guid.NewGuid().ToString("N")[..8]; + var result = await _orders.ForUser(testUserId, pagination, cancellationToken); + + // Should succeed even if no orders found (empty result is valid) + var repositoryWorks = result != null; + + healthData["RepositoryTestPassed"] = repositoryWorks; + healthData["RepositoryReturnedItems"] = result?.ItemCount ?? -1; + healthData["RepositoryPageSize"] = result?.PageSize ?? -1; + + if (!repositoryWorks) + { + _logger.LogWarning("Repository connectivity test failed"); + } + + return repositoryWorks; + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Repository connectivity test failed with exception"); + healthData["RepositoryTestPassed"] = false; + healthData["RepositoryTestError"] = ex.Message; + return false; + } + } +} \ No newline at end of file diff --git a/src/order-service/src/Orders.Api/Health/DynamoDbHealthCheck.cs b/src/order-service/src/Orders.Api/Health/DynamoDbHealthCheck.cs new file mode 100644 index 00000000..8c0b8fd6 --- /dev/null +++ b/src/order-service/src/Orders.Api/Health/DynamoDbHealthCheck.cs @@ -0,0 +1,94 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +using Amazon.DynamoDBv2; +using Amazon.DynamoDBv2.Model; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Orders.Api.Logging; + +namespace Orders.Api.Health; + +/// +/// Health check for DynamoDB connectivity and table status +/// +public class DynamoDbHealthCheck : IHealthCheck +{ + private readonly AmazonDynamoDBClient _dynamoDbClient; + private readonly IConfiguration _configuration; + private readonly ILogger _logger; + + public DynamoDbHealthCheck( + AmazonDynamoDBClient dynamoDbClient, + IConfiguration configuration, + ILogger logger) + { + _dynamoDbClient = dynamoDbClient ?? throw new ArgumentNullException(nameof(dynamoDbClient)); + _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } + + public async Task CheckHealthAsync( + HealthCheckContext context, + CancellationToken cancellationToken = default) + { + var correlationId = Guid.NewGuid().ToString(); + + try + { + _logger.LogInformation("Starting DynamoDB health check with correlation {CorrelationId}", correlationId); + + var tableName = _configuration["TABLE_NAME"]; + if (string.IsNullOrEmpty(tableName)) + { + const string message = "TABLE_NAME configuration is missing"; + _logger.LogError("DynamoDB health check failed: {Message}", message); + return HealthCheckResult.Unhealthy(message); + } + + var describeRequest = new DescribeTableRequest + { + TableName = tableName + }; + + var response = await _dynamoDbClient.DescribeTableAsync(describeRequest, cancellationToken); + + var healthData = new Dictionary + { + ["TableName"] = tableName, + ["TableStatus"] = response.Table.TableStatus.ToString(), + ["ItemCount"] = response.Table.ItemCount, + ["TableSizeBytes"] = response.Table.TableSizeBytes, + ["ReadCapacityUnits"] = response.Table.ProvisionedThroughput?.ReadCapacityUnits ?? 0, + ["WriteCapacityUnits"] = response.Table.ProvisionedThroughput?.WriteCapacityUnits ?? 0, + ["CheckTimestamp"] = DateTime.UtcNow, + ["CorrelationId"] = correlationId + }; + + if (response.Table.TableStatus == TableStatus.ACTIVE) + { + _logger.LogHealthCheckPassed(); + return HealthCheckResult.Healthy($"DynamoDB table '{tableName}' is active and healthy", data: healthData); + } + + if (response.Table.TableStatus == TableStatus.UPDATING) + { + _logger.LogInformation("DynamoDB table {TableName} is updating - health degraded", tableName); + return HealthCheckResult.Degraded($"DynamoDB table '{tableName}' is updating (status: {response.Table.TableStatus})", data: healthData); + } + + _logger.LogWarning("DynamoDB table {TableName} has unhealthy status: {Status}", tableName, response.Table.TableStatus); + return HealthCheckResult.Unhealthy($"DynamoDB table '{tableName}' is not active (status: {response.Table.TableStatus})", data: healthData); + } + catch (ResourceNotFoundException ex) + { + _logger.LogHealthCheckFailed("DynamoDB", ex); + return HealthCheckResult.Unhealthy("DynamoDB table not found", ex); + } + catch (Exception ex) + { + _logger.LogHealthCheckFailed("DynamoDB", ex); + return HealthCheckResult.Unhealthy("Cannot connect to DynamoDB", ex); + } + } +} \ No newline at end of file diff --git a/src/order-service/src/Orders.Api/Health/MemoryHealthCheck.cs b/src/order-service/src/Orders.Api/Health/MemoryHealthCheck.cs new file mode 100644 index 00000000..5abf0c2e --- /dev/null +++ b/src/order-service/src/Orders.Api/Health/MemoryHealthCheck.cs @@ -0,0 +1,120 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Orders.Api.Logging; + +namespace Orders.Api.Health; + +/// +/// Health check for memory usage and garbage collection metrics +/// +public class MemoryHealthCheck : IHealthCheck +{ + private const long MaxMemoryBytes = 500 * 1024 * 1024; // 500MB + private const long WarningThresholdBytes = (long)(MaxMemoryBytes * 0.8); // 80% of max + private readonly ILogger _logger; + + public MemoryHealthCheck(ILogger logger) + { + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } + + public Task CheckHealthAsync( + HealthCheckContext context, + CancellationToken cancellationToken = default) + { + var correlationId = Guid.NewGuid().ToString(); + + try + { + _logger.LogInformation("Starting memory health check with correlation {CorrelationId}", correlationId); + + var allocatedBytes = GC.GetTotalMemory(false); + var gen0Collections = GC.CollectionCount(0); + var gen1Collections = GC.CollectionCount(1); + var gen2Collections = GC.CollectionCount(2); + + // Calculate memory pressure indicators + var memoryPressure = allocatedBytes / (double)MaxMemoryBytes; + var totalCollections = gen0Collections + gen1Collections + gen2Collections; + + var healthData = new Dictionary + { + ["AllocatedBytes"] = allocatedBytes, + ["AllocatedMB"] = Math.Round(allocatedBytes / (1024.0 * 1024.0), 2), + ["MaxBytes"] = MaxMemoryBytes, + ["MaxMB"] = Math.Round(MaxMemoryBytes / (1024.0 * 1024.0), 2), + ["MemoryPressurePercent"] = Math.Round(memoryPressure * 100, 1), + ["Gen0Collections"] = gen0Collections, + ["Gen1Collections"] = gen1Collections, + ["Gen2Collections"] = gen2Collections, + ["TotalCollections"] = totalCollections, + ["CheckTimestamp"] = DateTime.UtcNow, + ["CorrelationId"] = correlationId + }; + + // Force a memory measurement with garbage collection for more accurate reading + if (allocatedBytes > WarningThresholdBytes) + { + _logger.LogInformation("Memory usage high, forcing garbage collection for accurate measurement"); + var beforeGC = allocatedBytes; + GC.Collect(); + GC.WaitForPendingFinalizers(); + GC.Collect(); + var afterGC = GC.GetTotalMemory(false); + + healthData["AllocatedBytesBeforeGC"] = beforeGC; + healthData["AllocatedBytesAfterGC"] = afterGC; + healthData["BytesFreedByGC"] = beforeGC - afterGC; + + allocatedBytes = afterGC; + memoryPressure = allocatedBytes / (double)MaxMemoryBytes; + healthData["MemoryPressurePercentAfterGC"] = Math.Round(memoryPressure * 100, 1); + } + + // Log performance metrics + _logger.LogPerformanceMetrics( + "MemoryHealthCheck", + 0, // Duration not relevant for this check + allocatedBytes / 1024 // Convert to KB + ); + + if (allocatedBytes >= MaxMemoryBytes) + { + _logger.LogHealthCheckFailed("Memory", new InvalidOperationException($"Memory usage {allocatedBytes} bytes exceeds maximum {MaxMemoryBytes} bytes")); + return Task.FromResult(HealthCheckResult.Unhealthy( + $"Memory usage {Math.Round(allocatedBytes / (1024.0 * 1024.0), 1)}MB exceeds limit of {Math.Round(MaxMemoryBytes / (1024.0 * 1024.0), 1)}MB", + data: healthData)); + } + + if (allocatedBytes >= WarningThresholdBytes) + { + _logger.LogPerformanceWarning("MemoryUsage", allocatedBytes / (1024 * 1024)); // MB + return Task.FromResult(HealthCheckResult.Degraded( + $"Memory usage {Math.Round(allocatedBytes / (1024.0 * 1024.0), 1)}MB is approaching limit of {Math.Round(MaxMemoryBytes / (1024.0 * 1024.0), 1)}MB", + data: healthData)); + } + + // Check for excessive garbage collection activity (potential memory pressure) + if (gen2Collections > 10 && gen2Collections > gen1Collections * 0.1) + { + _logger.LogWarning("High Gen2 garbage collection activity detected: {Gen2Collections} collections", gen2Collections); + return Task.FromResult(HealthCheckResult.Degraded( + $"High garbage collection activity detected - Gen2: {gen2Collections} collections may indicate memory pressure", + data: healthData)); + } + + _logger.LogHealthCheckPassed(); + return Task.FromResult(HealthCheckResult.Healthy( + $"Memory usage {Math.Round(allocatedBytes / (1024.0 * 1024.0), 1)}MB is within normal limits", + healthData)); + } + catch (Exception ex) + { + _logger.LogHealthCheckFailed("Memory", ex); + return Task.FromResult(HealthCheckResult.Unhealthy("Memory health check failed", ex)); + } + } +} \ No newline at end of file diff --git a/src/order-service/src/Orders.Api/Logging/LoggerMessageDefinitions.cs b/src/order-service/src/Orders.Api/Logging/LoggerMessageDefinitions.cs new file mode 100644 index 00000000..6c8c97bb --- /dev/null +++ b/src/order-service/src/Orders.Api/Logging/LoggerMessageDefinitions.cs @@ -0,0 +1,307 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +using Microsoft.Extensions.Logging; + +namespace Orders.Api.Logging; + +/// +/// High-performance logging message definitions using source generators - NO PII/SENSITIVE DATA +/// +public static partial class LogMessages +{ + // Order Creation Events + [LoggerMessage( + EventId = 1001, + Level = LogLevel.Information, + Message = "Order creation started with {ProductCount} products for user type {UserType}")] + public static partial void LogOrderCreationStarted( + this ILogger logger, + int productCount, + string userType); + + [LoggerMessage( + EventId = 1002, + Level = LogLevel.Information, + Message = "Order created successfully with type {OrderType} in {DurationMs}ms")] + public static partial void LogOrderCreated( + this ILogger logger, + string orderType, + long durationMs); + + [LoggerMessage( + EventId = 1003, + Level = LogLevel.Warning, + Message = "Order creation failed due to validation errors: {ValidationErrorCount} errors found")] + public static partial void LogOrderCreationValidationFailed( + this ILogger logger, + int validationErrorCount); + + [LoggerMessage( + EventId = 1004, + Level = LogLevel.Error, + Message = "Order creation failed unexpectedly for user type {UserType}")] + public static partial void LogOrderCreationFailed( + this ILogger logger, + string userType, + Exception exception); + + // Order Completion Events + [LoggerMessage( + EventId = 1010, + Level = LogLevel.Information, + Message = "Order completion started by admin user type {UserType}")] + public static partial void LogOrderCompletionStarted( + this ILogger logger, + string userType); + + [LoggerMessage( + EventId = 1011, + Level = LogLevel.Information, + Message = "Order completed successfully in {DurationMs}ms")] + public static partial void LogOrderCompleted( + this ILogger logger, + long durationMs); + + [LoggerMessage( + EventId = 1012, + Level = LogLevel.Warning, + Message = "Order completion denied - user type {UserType} lacks admin privileges")] + public static partial void LogOrderCompletionDenied( + this ILogger logger, + string userType); + + [LoggerMessage( + EventId = 1013, + Level = LogLevel.Warning, + Message = "Order completion failed - order not found or invalid state")] + public static partial void LogOrderCompletionNotFound( + this ILogger logger); + + // Order Retrieval Events + [LoggerMessage( + EventId = 1020, + Level = LogLevel.Information, + Message = "Order retrieval started for user type {UserType}")] + public static partial void LogOrderRetrievalStarted( + this ILogger logger, + string userType); + + [LoggerMessage( + EventId = 1021, + Level = LogLevel.Information, + Message = "Order retrieved successfully in {DurationMs}ms")] + public static partial void LogOrderRetrieved( + this ILogger logger, + long durationMs); + + [LoggerMessage( + EventId = 1022, + Level = LogLevel.Warning, + Message = "Order not found for retrieval request")] + public static partial void LogOrderNotFound( + this ILogger logger); + + // Pagination Events + [LoggerMessage( + EventId = 1030, + Level = LogLevel.Information, + Message = "Pagination query started: pageSize={PageSize}, operation={Operation}")] + public static partial void LogPaginationStarted( + this ILogger logger, + int pageSize, + string operation); + + [LoggerMessage( + EventId = 1031, + Level = LogLevel.Information, + Message = "Pagination completed: returned {ItemCount} items, hasMore={HasMorePages}, duration={DurationMs}ms")] + public static partial void LogPaginationCompleted( + this ILogger logger, + int itemCount, + bool hasMorePages, + long durationMs); + + [LoggerMessage( + EventId = 1032, + Level = LogLevel.Warning, + Message = "Pagination validation failed: pageSize={PageSize} exceeds maximum allowed")] + public static partial void LogPaginationValidationFailed( + this ILogger logger, + int pageSize); + + // Authentication & Authorization Events + [LoggerMessage( + EventId = 1040, + Level = LogLevel.Warning, + Message = "Authentication failed - missing or invalid user claims")] + public static partial void LogAuthenticationFailed( + this ILogger logger); + + [LoggerMessage( + EventId = 1041, + Level = LogLevel.Warning, + Message = "Authorization failed - user type {UserType} attempted restricted operation {Operation}")] + public static partial void LogAuthorizationFailed( + this ILogger logger, + string userType, + string operation); + + [LoggerMessage( + EventId = 1042, + Level = LogLevel.Information, + Message = "User authenticated successfully with type {UserType}")] + public static partial void LogUserAuthenticated( + this ILogger logger, + string userType); + + // Validation Events + [LoggerMessage( + EventId = 1050, + Level = LogLevel.Warning, + Message = "Input validation failed: {ErrorCount} validation errors in {Operation}")] + public static partial void LogValidationFailed( + this ILogger logger, + int errorCount, + string operation); + + [LoggerMessage( + EventId = 1051, + Level = LogLevel.Information, + Message = "Input validation passed for {Operation} in {DurationMs}ms")] + public static partial void LogValidationPassed( + this ILogger logger, + string operation, + long durationMs); + + // Database & External Service Events + [LoggerMessage( + EventId = 1060, + Level = LogLevel.Information, + Message = "Database operation started: {Operation}")] + public static partial void LogDatabaseOperationStarted( + this ILogger logger, + string operation); + + [LoggerMessage( + EventId = 1061, + Level = LogLevel.Information, + Message = "Database operation completed: {Operation} in {DurationMs}ms")] + public static partial void LogDatabaseOperationCompleted( + this ILogger logger, + string operation, + long durationMs); + + [LoggerMessage( + EventId = 1062, + Level = LogLevel.Warning, + Message = "Database operation failed: {Operation} - will retry")] + public static partial void LogDatabaseOperationRetry( + this ILogger logger, + string operation, + Exception exception); + + [LoggerMessage( + EventId = 1063, + Level = LogLevel.Error, + Message = "Database operation failed permanently: {Operation}")] + public static partial void LogDatabaseOperationFailed( + this ILogger logger, + string operation, + Exception exception); + + // Workflow Events + [LoggerMessage( + EventId = 1070, + Level = LogLevel.Information, + Message = "Workflow started: {WorkflowType} for order type {OrderType}")] + public static partial void LogWorkflowStarted( + this ILogger logger, + string workflowType, + string orderType); + + [LoggerMessage( + EventId = 1071, + Level = LogLevel.Information, + Message = "Workflow completed: {WorkflowType} in {DurationMs}ms")] + public static partial void LogWorkflowCompleted( + this ILogger logger, + string workflowType, + long durationMs); + + [LoggerMessage( + EventId = 1072, + Level = LogLevel.Error, + Message = "Workflow failed: {WorkflowType} for order type {OrderType}")] + public static partial void LogWorkflowFailed( + this ILogger logger, + string workflowType, + string orderType, + Exception exception); + + // Performance & Health Events + [LoggerMessage( + EventId = 1080, + Level = LogLevel.Information, + Message = "Performance metrics: {Operation} took {DurationMs}ms, memory delta: {MemoryDeltaKB}KB")] + public static partial void LogPerformanceMetrics( + this ILogger logger, + string operation, + long durationMs, + long memoryDeltaKB); + + [LoggerMessage( + EventId = 1081, + Level = LogLevel.Warning, + Message = "Performance warning: {Operation} took {DurationMs}ms (exceeds threshold)")] + public static partial void LogPerformanceWarning( + this ILogger logger, + string operation, + long durationMs); + + [LoggerMessage( + EventId = 1082, + Level = LogLevel.Information, + Message = "Health check completed: all systems operational")] + public static partial void LogHealthCheckPassed( + this ILogger logger); + + [LoggerMessage( + EventId = 1083, + Level = LogLevel.Error, + Message = "Health check failed: {ComponentName} is unhealthy")] + public static partial void LogHealthCheckFailed( + this ILogger logger, + string componentName, + Exception exception); + + // Business Intelligence Events (NO PII - only aggregate data) + [LoggerMessage( + EventId = 1090, + Level = LogLevel.Information, + Message = "Business event: {EventType} for {OrderType} order with {ProductCount} products")] + public static partial void LogBusinessEvent( + this ILogger logger, + string eventType, + string orderType, + int productCount); + + [LoggerMessage( + EventId = 1091, + Level = LogLevel.Information, + Message = "Order funnel stage: {Stage} reached for {OrderType} order")] + public static partial void LogOrderFunnelStage( + this ILogger logger, + string stage, + string orderType); + + [LoggerMessage( + EventId = 1092, + Level = LogLevel.Information, + Message = "User segment activity: {UserTier} users performed {Operation}")] + public static partial void LogUserSegmentActivity( + this ILogger logger, + string userTier, + string operation); +} \ No newline at end of file diff --git a/src/order-service/src/Orders.Api/Logging/StructuredLogging.cs b/src/order-service/src/Orders.Api/Logging/StructuredLogging.cs new file mode 100644 index 00000000..9785daac --- /dev/null +++ b/src/order-service/src/Orders.Api/Logging/StructuredLogging.cs @@ -0,0 +1,333 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +using System.Diagnostics; + +namespace Orders.Api.Logging; + +/// +/// Structured logging context for order operations - NO PII/SENSITIVE DATA +/// +public readonly record struct OrderOperationContext +{ + /// + /// Gets the correlation ID for request tracking + /// + public string CorrelationId { get; init; } + + /// + /// Gets the operation name being performed + /// + public string Operation { get; init; } + + /// + /// Gets the number of products in the order (for metrics only) + /// + public int? ProductCount { get; init; } + + /// + /// Gets the order type (Standard, Priority, etc.) + /// + public string? OrderType { get; init; } + + /// + /// Gets the user type (PREMIUM, STANDARD, ADMIN) for authorization context + /// + public string? UserType { get; init; } + + /// + /// Gets the execution duration in milliseconds + /// + public long? DurationMs { get; init; } + + /// + /// Gets the HTTP status code result + /// + public int? StatusCode { get; init; } + + /// + /// Gets whether the operation was successful + /// + public bool? Success { get; init; } + + /// + /// Gets the validation error count (if any) + /// + public int? ValidationErrorCount { get; init; } + + /// + /// Gets the error category for failures + /// + public string? ErrorCategory { get; init; } +} + +/// +/// Structured logging context for pagination operations +/// +public readonly record struct PaginationContext +{ + /// + /// Gets the correlation ID for request tracking + /// + public string CorrelationId { get; init; } + + /// + /// Gets the requested page size + /// + public int PageSize { get; init; } + + /// + /// Gets the number of items returned + /// + public int ItemsReturned { get; init; } + + /// + /// Gets whether there are more pages available + /// + public bool HasMorePages { get; init; } + + /// + /// Gets the operation being paginated + /// + public string Operation { get; init; } + + /// + /// Gets the execution duration in milliseconds + /// + public long DurationMs { get; init; } +} + +/// +/// Performance metrics context for operations +/// +public readonly record struct PerformanceContext +{ + /// + /// Gets the correlation ID for request tracking + /// + public string CorrelationId { get; init; } + + /// + /// Gets the operation name + /// + public string Operation { get; init; } + + /// + /// Gets the execution duration in milliseconds + /// + public long DurationMs { get; init; } + + /// + /// Gets the database query count + /// + public int? DatabaseQueries { get; init; } + + /// + /// Gets the external service call count + /// + public int? ExternalCalls { get; init; } + + /// + /// Gets whether the operation succeeded + /// + public bool Success { get; init; } + + /// + /// Gets memory usage in bytes + /// + public long? MemoryUsageBytes { get; init; } +} + +/// +/// Business metrics context for order lifecycle tracking +/// +public readonly record struct BusinessMetricsContext +{ + /// + /// Gets the correlation ID for request tracking + /// + public string CorrelationId { get; init; } + + /// + /// Gets the business event type + /// + public string EventType { get; init; } + + /// + /// Gets the order type for business analysis + /// + public string? OrderType { get; init; } + + /// + /// Gets the user tier for segmentation analysis + /// + public string? UserTier { get; init; } + + /// + /// Gets the product count for basket analysis + /// + public int? ProductCount { get; init; } + + /// + /// Gets the timestamp for temporal analysis + /// + public DateTime Timestamp { get; init; } + + /// + /// Gets the processing stage for funnel analysis + /// + public string? ProcessingStage { get; init; } +} + +/// +/// Extensions for structured logging that ensure no PII is logged +/// +public static class StructuredLoggingExtensions +{ + /// + /// Logs order operation with structured context - NO PII + /// + public static void LogOrderOperation( + this ILogger logger, + LogLevel level, + string message, + OrderOperationContext context, + Exception? exception = null) + { + using var scope = logger.BeginScope(new Dictionary + { + ["CorrelationId"] = context.CorrelationId, + ["Operation"] = context.Operation, + ["ProductCount"] = context.ProductCount ?? 0, + ["OrderType"] = context.OrderType ?? "Unknown", + ["UserType"] = context.UserType ?? "Unknown", + ["DurationMs"] = context.DurationMs ?? 0, + ["StatusCode"] = context.StatusCode ?? 0, + ["Success"] = context.Success ?? false, + ["ValidationErrorCount"] = context.ValidationErrorCount ?? 0, + ["ErrorCategory"] = context.ErrorCategory ?? "None" + }); + + logger.Log(level, exception, message); + } + + /// + /// Logs pagination operation with structured context + /// + public static void LogPaginationOperation( + this ILogger logger, + string message, + PaginationContext context) + { + using var scope = logger.BeginScope(new Dictionary + { + ["CorrelationId"] = context.CorrelationId, + ["Operation"] = context.Operation, + ["PageSize"] = context.PageSize, + ["ItemsReturned"] = context.ItemsReturned, + ["HasMorePages"] = context.HasMorePages, + ["DurationMs"] = context.DurationMs + }); + + logger.LogInformation(message); + } + + /// + /// Logs performance metrics with structured context + /// + public static void LogPerformanceMetrics( + this ILogger logger, + string message, + PerformanceContext context) + { + using var scope = logger.BeginScope(new Dictionary + { + ["CorrelationId"] = context.CorrelationId, + ["Operation"] = context.Operation, + ["DurationMs"] = context.DurationMs, + ["DatabaseQueries"] = context.DatabaseQueries ?? 0, + ["ExternalCalls"] = context.ExternalCalls ?? 0, + ["Success"] = context.Success, + ["MemoryUsageBytes"] = context.MemoryUsageBytes ?? 0 + }); + + logger.LogInformation(message); + } + + /// + /// Logs business metrics with structured context - NO PII + /// + public static void LogBusinessMetrics( + this ILogger logger, + string message, + BusinessMetricsContext context) + { + using var scope = logger.BeginScope(new Dictionary + { + ["CorrelationId"] = context.CorrelationId, + ["EventType"] = context.EventType, + ["OrderType"] = context.OrderType ?? "Unknown", + ["UserTier"] = context.UserTier ?? "Unknown", + ["ProductCount"] = context.ProductCount ?? 0, + ["Timestamp"] = context.Timestamp, + ["ProcessingStage"] = context.ProcessingStage ?? "Unknown" + }); + + logger.LogInformation(message); + } + + /// + /// Creates a performance tracking scope that automatically logs metrics + /// + public static IDisposable BeginPerformanceScope( + this ILogger logger, + string operation, + string correlationId) + { + return new PerformanceScope(logger, operation, correlationId); + } +} + +/// +/// Performance tracking scope that automatically measures and logs execution time +/// +internal sealed class PerformanceScope : IDisposable +{ + private readonly ILogger _logger; + private readonly string _operation; + private readonly string _correlationId; + private readonly Stopwatch _stopwatch; + private readonly long _startMemory; + private bool _disposed; + + public PerformanceScope(ILogger logger, string operation, string correlationId) + { + _logger = logger; + _operation = operation; + _correlationId = correlationId; + _stopwatch = Stopwatch.StartNew(); + _startMemory = GC.GetTotalMemory(false); + } + + public void Dispose() + { + if (_disposed) return; + + _stopwatch.Stop(); + var endMemory = GC.GetTotalMemory(false); + var memoryDelta = endMemory - _startMemory; + + var context = new PerformanceContext + { + CorrelationId = _correlationId, + Operation = _operation, + DurationMs = _stopwatch.ElapsedMilliseconds, + Success = true, // Assume success unless explicitly marked otherwise + MemoryUsageBytes = memoryDelta + }; + + _logger.LogPerformanceMetrics($"Operation {_operation} completed", context); + _disposed = true; + } +} \ No newline at end of file diff --git a/src/order-service/src/Orders.Api/Middleware/CorrelationIdMiddleware.cs b/src/order-service/src/Orders.Api/Middleware/CorrelationIdMiddleware.cs new file mode 100644 index 00000000..2f2e12bc --- /dev/null +++ b/src/order-service/src/Orders.Api/Middleware/CorrelationIdMiddleware.cs @@ -0,0 +1,33 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +namespace Orders.Api.Middleware; + +/// +/// Middleware that handles correlation ID generation and propagation +/// +public class CorrelationIdMiddleware +{ + private readonly RequestDelegate _next; + private const string CorrelationIdHeader = "X-Correlation-ID"; + + public CorrelationIdMiddleware(RequestDelegate next) + { + _next = next; + } + + public async Task InvokeAsync(HttpContext context) + { + var correlationId = context.Request.Headers[CorrelationIdHeader].FirstOrDefault() + ?? Guid.NewGuid().ToString(); + + // Store in context items for use by other middleware and handlers + context.Items["CorrelationId"] = correlationId; + + // Add to response headers + context.Response.Headers[CorrelationIdHeader] = correlationId; + + await _next(context); + } +} \ No newline at end of file diff --git a/src/order-service/src/Orders.Api/Middleware/GlobalExceptionHandlingMiddleware.cs b/src/order-service/src/Orders.Api/Middleware/GlobalExceptionHandlingMiddleware.cs index 4ba7dec4..70e2ebf1 100644 --- a/src/order-service/src/Orders.Api/Middleware/GlobalExceptionHandlingMiddleware.cs +++ b/src/order-service/src/Orders.Api/Middleware/GlobalExceptionHandlingMiddleware.cs @@ -3,7 +3,9 @@ // Copyright 2025 Datadog, Inc. using System.Text.Json; +using Orders.Api.Models; using Orders.Core; +using Orders.Core.Domain.Exceptions; namespace Orders.Api.Middleware; @@ -37,27 +39,72 @@ public async Task InvokeAsync(HttpContext context) private static Task HandleExceptionAsync(HttpContext context, Exception exception) { context.Response.ContentType = "application/json"; + var correlationId = context.Items["CorrelationId"]?.ToString() ?? context.TraceIdentifier; - var statusCode = exception switch + var (statusCode, errorCode, message, details) = exception switch { - OrderNotConfirmedException => StatusCodes.Status400BadRequest, - KeyNotFoundException => StatusCodes.Status404NotFound, - ArgumentException => StatusCodes.Status400BadRequest, - UnauthorizedAccessException => StatusCodes.Status401Unauthorized, - _ => StatusCodes.Status500InternalServerError + OrderValidationException validationEx => ( + StatusCodes.Status400BadRequest, + ErrorCodes.ValidationError, + "Order validation failed", + validationEx.Message + ), + Orders.Core.Domain.Exceptions.OrderNotConfirmedException => ( + StatusCodes.Status409Conflict, + ErrorCodes.InvalidState, + "Order must be confirmed before this operation", + exception.Message + ), + InvalidOrderStateException => ( + StatusCodes.Status409Conflict, + ErrorCodes.InvalidState, + "Invalid order state transition", + exception.Message + ), + OrderNotFoundException => ( + StatusCodes.Status404NotFound, + ErrorCodes.NotFound, + "Order not found", + exception.Message + ), + WorkflowException => ( + StatusCodes.Status503ServiceUnavailable, + ErrorCodes.ServiceUnavailable, + "Workflow service unavailable", + "The order workflow service is currently unavailable. Please try again later." + ), + ArgumentException => ( + StatusCodes.Status400BadRequest, + ErrorCodes.ValidationError, + "Invalid input provided", + exception.Message + ), + UnauthorizedAccessException => ( + StatusCodes.Status401Unauthorized, + ErrorCodes.Unauthorized, + "Authentication required", + "Valid authentication credentials are required to access this resource" + ), + _ => ( + StatusCodes.Status500InternalServerError, + ErrorCodes.InternalError, + "An unexpected error occurred", + "An internal server error occurred. Please try again later." + ) }; context.Response.StatusCode = statusCode; - var response = new - { - StatusCode = statusCode, - Message = exception.Message, - TraceId = context.TraceIdentifier - }; + var errorResponse = new ErrorResponse( + errorCode, + message, + details, + null, + correlationId + ); var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; - return context.Response.WriteAsync(JsonSerializer.Serialize(response, options)); + return context.Response.WriteAsync(JsonSerializer.Serialize(errorResponse, options)); } } \ No newline at end of file diff --git a/src/order-service/src/Orders.Api/Middleware/MiddlewareExtensions.cs b/src/order-service/src/Orders.Api/Middleware/MiddlewareExtensions.cs index 8355dd9e..189e2721 100644 --- a/src/order-service/src/Orders.Api/Middleware/MiddlewareExtensions.cs +++ b/src/order-service/src/Orders.Api/Middleware/MiddlewareExtensions.cs @@ -9,6 +9,14 @@ namespace Orders.Api.Middleware; /// public static class MiddlewareExtensions { + /// + /// Adds the correlation ID middleware to the application pipeline + /// + public static IApplicationBuilder UseCorrelationId(this IApplicationBuilder app) + { + return app.UseMiddleware(); + } + /// /// Adds the global exception handling middleware to the application pipeline /// diff --git a/src/order-service/src/Orders.Api/Models/CompleteOrderRequest.cs b/src/order-service/src/Orders.Api/Models/CompleteOrderRequest.cs new file mode 100644 index 00000000..0ea983b1 --- /dev/null +++ b/src/order-service/src/Orders.Api/Models/CompleteOrderRequest.cs @@ -0,0 +1,48 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +using System.Text.Json.Serialization; +using FluentValidation; + +namespace Orders.Api.Models; + +/// +/// Request model for completing an order +/// +public record CompleteOrderRequest +{ + /// + /// Gets or sets the order ID to complete + /// + [JsonPropertyName("orderId")] + public string OrderId { get; set; } = ""; + + /// + /// Gets or sets the user ID that owns the order + /// + [JsonPropertyName("userId")] + public string UserId { get; set; } = ""; +} + +/// +/// Validator for the CompleteOrderRequest +/// +public class CompleteOrderRequestValidator : AbstractValidator +{ + /// + /// Initializes a new instance of the validator with validation rules + /// + public CompleteOrderRequestValidator() + { + RuleFor(x => x.OrderId) + .NotEmpty().WithMessage("Order ID is required") + .Length(1, 100).WithMessage("Order ID must be between 1 and 100 characters") + .Matches(@"^[a-zA-Z0-9\-_]+$").WithMessage("Order ID contains invalid characters"); + + RuleFor(x => x.UserId) + .NotEmpty().WithMessage("User ID is required") + .Length(1, 100).WithMessage("User ID must be between 1 and 100 characters") + .Matches(@"^[a-zA-Z0-9\-_@.]+$").WithMessage("User ID contains invalid characters"); + } +} \ No newline at end of file diff --git a/src/order-service/src/Orders.Api/Models/CreateOrderRequest.cs b/src/order-service/src/Orders.Api/Models/CreateOrderRequest.cs index 17cba4df..3a3cffe9 100644 --- a/src/order-service/src/Orders.Api/Models/CreateOrderRequest.cs +++ b/src/order-service/src/Orders.Api/Models/CreateOrderRequest.cs @@ -28,11 +28,23 @@ public class CreateOrderRequestValidator : AbstractValidator public CreateOrderRequestValidator() { RuleFor(x => x.Products) - .NotEmpty().WithMessage("Products cannot be empty") - .Must(p => p.Length <= 100).WithMessage("Too many products in a single order"); + .NotNull().WithMessage("Products array is required") + .NotEmpty().WithMessage("At least one product must be specified") + .Must(p => p.Length <= 50).WithMessage("Cannot order more than 50 products at once") + .Must(p => p.Length >= 1).WithMessage("At least one product must be specified") + .Must(HaveUniqueProducts).WithMessage("Duplicate products are not allowed"); RuleForEach(x => x.Products) .NotEmpty().WithMessage("Product ID cannot be empty") - .Length(1, 50).WithMessage("Product ID must be between 1 and 50 characters"); + .Length(1, 50).WithMessage("Product ID must be between 1 and 50 characters") + .Matches(@"^[a-zA-Z0-9\-_]+$").WithMessage("Product ID contains invalid characters"); + } + + /// + /// Validates that all products in the order are unique + /// + private static bool HaveUniqueProducts(string[] products) + { + return products.Length == products.Distinct().Count(); } } \ No newline at end of file diff --git a/src/order-service/src/Orders.Api/Models/ErrorResponse.cs b/src/order-service/src/Orders.Api/Models/ErrorResponse.cs new file mode 100644 index 00000000..632a4880 --- /dev/null +++ b/src/order-service/src/Orders.Api/Models/ErrorResponse.cs @@ -0,0 +1,37 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +namespace Orders.Api.Models; + +/// +/// Standard error response model for API errors +/// +public record ErrorResponse( + string Error, + string Message, + string? Details = null, + Dictionary? ValidationErrors = null, + string? CorrelationId = null); + +/// +/// Validation-specific error response model +/// +public record ValidationErrorResponse( + string Error, + Dictionary ValidationErrors, + string? CorrelationId = null); + +/// +/// Error codes used throughout the API +/// +public static class ErrorCodes +{ + public const string ValidationError = "VALIDATION_ERROR"; + public const string InvalidState = "INVALID_STATE"; + public const string NotFound = "NOT_FOUND"; + public const string Unauthorized = "UNAUTHORIZED"; + public const string Forbidden = "FORBIDDEN"; + public const string InternalError = "INTERNAL_ERROR"; + public const string ServiceUnavailable = "SERVICE_UNAVAILABLE"; +} \ No newline at end of file diff --git a/src/order-service/src/Orders.Api/Models/RouteParameterValidators.cs b/src/order-service/src/Orders.Api/Models/RouteParameterValidators.cs new file mode 100644 index 00000000..4863bed0 --- /dev/null +++ b/src/order-service/src/Orders.Api/Models/RouteParameterValidators.cs @@ -0,0 +1,102 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +using FluentValidation; + +namespace Orders.Api.Models; + +/// +/// Request model for route parameters that need validation +/// +public record GetOrderRequest +{ + /// + /// Gets or sets the order ID from the route + /// + public string OrderId { get; set; } = ""; + + /// + /// Gets or sets the user ID (from claims, but validated) + /// + public string? UserId { get; set; } +} + +/// +/// Validator for GetOrderRequest route parameters +/// +public class GetOrderRequestValidator : AbstractValidator +{ + /// + /// Initializes a new instance of the validator with validation rules + /// + public GetOrderRequestValidator() + { + RuleFor(x => x.OrderId) + .NotEmpty().WithMessage("Order ID is required") + .Length(1, 100).WithMessage("Order ID must be between 1 and 100 characters") + .Matches(@"^[a-zA-Z0-9\-_]+$").WithMessage("Order ID contains invalid characters"); + + RuleFor(x => x.UserId) + .NotEmpty().WithMessage("User ID is required") + .Length(1, 100).WithMessage("User ID must be between 1 and 100 characters") + .Matches(@"^[a-zA-Z0-9\-_@.]+$").WithMessage("User ID contains invalid characters") + .When(x => !string.IsNullOrEmpty(x.UserId)); + } +} + +/// +/// Request model for pagination query parameters +/// +public record PaginationQueryRequest +{ + /// + /// Gets or sets the page size + /// + public int PageSize { get; set; } = 20; + + /// + /// Gets or sets the page token for continuation + /// + public string? PageToken { get; set; } +} + +/// +/// Validator for pagination query parameters +/// +public class PaginationQueryRequestValidator : AbstractValidator +{ + /// + /// Initializes a new instance of the validator with validation rules + /// + public PaginationQueryRequestValidator() + { + RuleFor(x => x.PageSize) + .GreaterThan(0).WithMessage("Page size must be greater than 0") + .LessThanOrEqualTo(100).WithMessage("Page size cannot exceed 100"); + + RuleFor(x => x.PageToken) + .Length(1, 1000).WithMessage("Page token must be between 1 and 1000 characters") + .Must(BeValidBase64Token).WithMessage("Page token format is invalid") + .When(x => !string.IsNullOrEmpty(x.PageToken)); + } + + /// + /// Validates that a string is a valid base64 encoded token + /// + private static bool BeValidBase64Token(string? token) + { + if (string.IsNullOrEmpty(token)) + return true; + + try + { + Convert.FromBase64String(token); + return true; + } + catch + { + return false; + } + } +} \ No newline at end of file diff --git a/src/order-service/src/Orders.Api/Orders.Api.csproj b/src/order-service/src/Orders.Api/Orders.Api.csproj index b0719f98..55afc121 100644 --- a/src/order-service/src/Orders.Api/Orders.Api.csproj +++ b/src/order-service/src/Orders.Api/Orders.Api.csproj @@ -20,6 +20,7 @@ + diff --git a/src/order-service/src/Orders.Api/Program.cs b/src/order-service/src/Orders.Api/Program.cs index a56b6e35..bac960a7 100644 --- a/src/order-service/src/Orders.Api/Program.cs +++ b/src/order-service/src/Orders.Api/Program.cs @@ -11,9 +11,13 @@ using Orders.Api.GetUserOrders; using Orders.Api.Middleware; using Orders.Api.Models; +using Orders.Api.Health; +using Orders.Api.RateLimiting; +using Orders.Api.Versioning; using Orders.Core; using Serilog; using Serilog.Formatting.Compact; +using System.Text.Json; try { @@ -33,6 +37,15 @@ builder.Services.AddValidatorsFromAssemblyContaining(); builder.Services.AddValidatorsFromAssemblyContaining(); + // Add comprehensive health checks + builder.Services.AddHealthChecks() + .AddCheck("dynamodb", tags: new[] { "ready", "database" }) + .AddCheck("memory", tags: new[] { "ready", "system" }) + .AddCheck("application", tags: new[] { "ready", "application" }); + + // Add rate limiting metrics + builder.Services.AddSingleton(); + // Add API versioning builder.Services.AddProblemDetails(); builder.Services.AddEndpointsApiExplorer(); @@ -45,24 +58,124 @@ new HeaderApiVersionReader("X-API-Version") ); }); - builder.Services.AddEndpointsApiExplorer(); + // Enhanced rate limiting with user-based policies builder.Services.AddRateLimiter(options => { + // Default policy for anonymous/standard users + options.AddPolicy(RateLimitPolicies.Default, httpContext => + RateLimitPartition.GetFixedWindowLimiter("default", partition => + new FixedWindowRateLimiterOptions + { + PermitLimit = 30, + Window = TimeSpan.FromMinutes(1), + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2 + })); + + // Premium users get higher limits + options.AddPolicy(RateLimitPolicies.Premium, httpContext => + RateLimitPartition.GetSlidingWindowLimiter("premium", partition => + new SlidingWindowRateLimiterOptions + { + PermitLimit = 200, + Window = TimeSpan.FromMinutes(1), + SegmentsPerWindow = 6, // 10-second segments for smoother rate limiting + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 10 + })); + + // Read operations have higher limits + options.AddPolicy(RateLimitPolicies.ReadOnly, httpContext => + RateLimitPartition.GetSlidingWindowLimiter("readonly", partition => + new SlidingWindowRateLimiterOptions + { + PermitLimit = 100, + Window = TimeSpan.FromMinutes(1), + SegmentsPerWindow = 4, // 15-second segments + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 5 + })); + + // Write operations have stricter limits + options.AddPolicy(RateLimitPolicies.WriteOnly, httpContext => + RateLimitPartition.GetFixedWindowLimiter("writeonly", partition => + new FixedWindowRateLimiterOptions + { + PermitLimit = 20, + Window = TimeSpan.FromMinutes(1), + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 2 + })); + + // Admin operations have very strict limits + options.AddPolicy(RateLimitPolicies.AdminOperations, httpContext => + RateLimitPartition.GetFixedWindowLimiter("admin", partition => + new FixedWindowRateLimiterOptions + { + PermitLimit = 10, + Window = TimeSpan.FromMinutes(1), + QueueProcessingOrder = QueueProcessingOrder.OldestFirst, + QueueLimit = 1 + })); + + // Global limiter with user-type based partitioning options.GlobalLimiter = PartitionedRateLimiter.Create(httpContext => { - var userDetails = httpContext.User?.Claims?.ExtractUserId(); + var userClaims = httpContext.User?.Claims?.ExtractUserId(); + var userType = userClaims?.UserType ?? "ANONYMOUS"; + var userId = userClaims?.UserId ?? httpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown"; - return RateLimitPartition.GetFixedWindowLimiter( - userDetails?.UserId ?? httpContext.Request.Headers.Host.ToString(), - partition => new FixedWindowRateLimiterOptions + // Create partition key that doesn't include PII but allows proper rate limiting + var partitionKey = $"{userType}:{userId.GetHashCode():X}"; // Hash user ID for privacy + + return RateLimitPartition.GetSlidingWindowLimiter(partitionKey, partition => + { + var (permitLimit, queueLimit) = userType switch + { + "PREMIUM" => (200, 10), + "ADMIN" => (150, 8), + "STANDARD" => (60, 5), + _ => (30, 2) + }; + + return new SlidingWindowRateLimiterOptions { - AutoReplenishment = true, - PermitLimit = 60, - QueueLimit = 0, - Window = TimeSpan.FromMinutes(1) - }); + PermitLimit = permitLimit, + QueueLimit = queueLimit, + Window = TimeSpan.FromMinutes(1), + SegmentsPerWindow = 6 // 10-second segments for smoother limiting + }; + }); }); + + // Custom rejection response with proper headers + options.OnRejected = async (context, token) => + { + var metrics = context.HttpContext.RequestServices.GetService(); + var userClaims = context.HttpContext.User?.Claims?.ExtractUserId(); + var userType = userClaims?.UserType ?? "ANONYMOUS"; + var endpoint = context.HttpContext.Request.Path.ToString(); + + // Record rejection metrics + metrics?.RecordRejected("global", userType, endpoint); + + context.HttpContext.Response.StatusCode = 429; + context.HttpContext.Response.Headers["Retry-After"] = "60"; + context.HttpContext.Response.Headers["X-RateLimit-Policy"] = "global"; + context.HttpContext.Response.Headers["X-RateLimit-Remaining"] = "0"; + + var response = new + { + error = "RATE_LIMIT_EXCEEDED", + message = "Rate limit exceeded. Please try again later.", + retryAfter = 60, + userType = userType, + correlationId = context.HttpContext.Items["CorrelationId"]?.ToString() ?? Guid.NewGuid().ToString() + }; + + await context.HttpContext.Response.WriteAsJsonAsync(response, cancellationToken: token); + }; }); // Add API documentation @@ -95,8 +208,14 @@ var app = builder.Build(); + // Add correlation ID middleware first + app.UseCorrelationId(); + app.UseRateLimiter(); + // Add API deprecation middleware + app.UseApiDeprecation(); + // Add global exception handling app.UseGlobalExceptionHandling(); @@ -120,50 +239,119 @@ var orders = app.NewVersionedApi("Orders"); - // Add health check endpoint with more detailed status - orders.MapGet("/health", () => + // Comprehensive health check endpoints + app.MapHealthChecks("/health", new Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions + { + ResponseWriter = async (context, report) => { - return Results.Ok(new + context.Response.ContentType = "application/json"; + + var result = JsonSerializer.Serialize(new + { + status = report.Status.ToString(), + timestamp = DateTime.UtcNow, + duration = report.TotalDuration.TotalMilliseconds, + version = "1.0.0", + checks = report.Entries.Select(e => new + { + name = e.Key, + status = e.Value.Status.ToString(), + description = e.Value.Description, + duration = e.Value.Duration.TotalMilliseconds, + data = e.Value.Data + }) + }, new JsonSerializerOptions { - Status = "Healthy", - Timestamp = DateTime.UtcNow, - Version = "1.0.0" // Increment this when deploying new versions + PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); - }) - .HasApiVersion(1.0) - .WithDescription("Health check endpoint") - .WithTags("Monitoring"); - // Version 1 API endpoints + + await context.Response.WriteAsync(result); + } + }); + + // Readiness check for load balancers and orchestrators + app.MapHealthChecks("/health/ready", new Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions + { + Predicate = check => check.Tags.Contains("ready"), + ResponseWriter = async (context, report) => + { + var result = JsonSerializer.Serialize(new + { + status = report.Status.ToString(), + timestamp = DateTime.UtcNow + }, new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }); + context.Response.ContentType = "application/json"; + await context.Response.WriteAsync(result); + } + }); + + // Simple liveness check for Kubernetes + app.MapHealthChecks("/health/live", new Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions + { + Predicate = _ => false, // Only basic runtime health + ResponseWriter = async (context, report) => + { + var result = JsonSerializer.Serialize(new + { + status = "Healthy", + timestamp = DateTime.UtcNow + }, new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }); + context.Response.ContentType = "application/json"; + await context.Response.WriteAsync(result); + } + }); + // Version 1 API endpoints with specific rate limiting policies orders.MapGet("/orders", GetUserOrdersHandler.Handle) .HasApiVersion(1.0) .WithDescription("Get orders for the authenticated user") + .RequireRateLimiting(RateLimitPolicies.ReadOnly) .Produces>(200) - .ProducesProblem(401); - ; + .ProducesProblem(401) + .ProducesProblem(429); + orders.MapGet("/orders/confirmed", ConfirmedOrdersHandler.Handle) .HasApiVersion(1.0) - .WithDescription("Get all confirmed orders") + .WithDescription("Get all confirmed orders (Admin only)") + .RequireRateLimiting(RateLimitPolicies.AdminOperations) .Produces>(200) - .ProducesProblem(401); + .ProducesProblem(401) + .ProducesProblem(403) + .ProducesProblem(429); + orders.MapGet("/orders/{OrderId}", GetOrderDetailsHandler.Handle) .HasApiVersion(1.0) .WithDescription("Get details for a specific order") + .RequireRateLimiting(RateLimitPolicies.ReadOnly) .Produces(200) .ProducesProblem(401) - .ProducesProblem(404); + .ProducesProblem(404) + .ProducesProblem(429); + orders.MapPost("/orders", CreateOrderHandler.Handle) .HasApiVersion(1.0) .WithDescription("Create a new order") + .RequireRateLimiting(RateLimitPolicies.WriteOnly) .Produces(201) .ProducesProblem(400) - .ProducesProblem(401); + .ProducesProblem(401) + .ProducesProblem(429); + orders.MapPost("/orders/{OrderId}/complete", CompleteOrderHandler.Handle) .HasApiVersion(1.0) - .WithDescription("Mark an order as complete") + .WithDescription("Mark an order as complete (Admin only)") + .RequireRateLimiting(RateLimitPolicies.AdminOperations) .Produces(204) .ProducesProblem(400) .ProducesProblem(401) - .ProducesProblem(404); + .ProducesProblem(403) + .ProducesProblem(404) + .ProducesProblem(429); Log.Information("Starting up orders API version 1.0.0"); diff --git a/src/order-service/src/Orders.Api/RateLimiting/RateLimitPolicies.cs b/src/order-service/src/Orders.Api/RateLimiting/RateLimitPolicies.cs new file mode 100644 index 00000000..d280d07c --- /dev/null +++ b/src/order-service/src/Orders.Api/RateLimiting/RateLimitPolicies.cs @@ -0,0 +1,36 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +namespace Orders.Api.RateLimiting; + +/// +/// Defines rate limiting policy names for different types of operations +/// +public static class RateLimitPolicies +{ + /// + /// Default policy for anonymous users and fallback scenarios + /// + public const string Default = "DefaultPolicy"; + + /// + /// Enhanced limits for premium/authenticated users + /// + public const string Premium = "PremiumPolicy"; + + /// + /// Higher limits for read-only operations (GET requests) + /// + public const string ReadOnly = "ReadOnlyPolicy"; + + /// + /// Lower limits for write operations (POST, PUT, DELETE) + /// + public const string WriteOnly = "WriteOnlyPolicy"; + + /// + /// Strict limits for admin operations + /// + public const string AdminOperations = "AdminOperationsPolicy"; +} \ No newline at end of file diff --git a/src/order-service/src/Orders.Api/RateLimiting/RateLimitingMetrics.cs b/src/order-service/src/Orders.Api/RateLimiting/RateLimitingMetrics.cs new file mode 100644 index 00000000..70aa03c2 --- /dev/null +++ b/src/order-service/src/Orders.Api/RateLimiting/RateLimitingMetrics.cs @@ -0,0 +1,81 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +using System.Diagnostics.Metrics; + +namespace Orders.Api.RateLimiting; + +/// +/// Metrics collection for rate limiting operations - NO PII data +/// +public class RateLimitingMetrics +{ + private readonly Counter _requestsAllowed; + private readonly Counter _requestsRejected; + private readonly Histogram _queueTime; + private readonly Counter _requestsByUserType; + + public RateLimitingMetrics(IMeterFactory meterFactory) + { + var meter = meterFactory.Create("Orders.RateLimiting"); + + _requestsAllowed = meter.CreateCounter( + "rate_limit_requests_allowed_total", + "Total number of requests allowed by rate limiter"); + + _requestsRejected = meter.CreateCounter( + "rate_limit_requests_rejected_total", + "Total number of requests rejected by rate limiter"); + + _queueTime = meter.CreateHistogram( + "rate_limit_queue_duration_seconds", + "Time spent waiting in rate limiter queue"); + + _requestsByUserType = meter.CreateCounter( + "rate_limit_requests_by_user_type_total", + "Total requests categorized by user type (no PII)"); + } + + /// + /// Records a request that was allowed by the rate limiter + /// + public void RecordAllowed(string policy, string userType, string endpoint) + { + _requestsAllowed.Add(1, + new KeyValuePair("policy", policy), + new KeyValuePair("user_type", userType), + new KeyValuePair("endpoint", endpoint)); + } + + /// + /// Records a request that was rejected by the rate limiter + /// + public void RecordRejected(string policy, string userType, string endpoint) + { + _requestsRejected.Add(1, + new KeyValuePair("policy", policy), + new KeyValuePair("user_type", userType), + new KeyValuePair("endpoint", endpoint)); + } + + /// + /// Records time spent waiting in the rate limiter queue + /// + public void RecordQueueTime(double queueTimeSeconds, string policy, string userType) + { + _queueTime.Record(queueTimeSeconds, + new KeyValuePair("policy", policy), + new KeyValuePair("user_type", userType)); + } + + /// + /// Records request counts by user type for analytics (NO PII) + /// + public void RecordRequestByUserType(string userType, string operation) + { + _requestsByUserType.Add(1, + new KeyValuePair("user_type", userType), + new KeyValuePair("operation", operation)); + } +} \ No newline at end of file diff --git a/src/order-service/src/Orders.Api/TraceExtensions.cs b/src/order-service/src/Orders.Api/TraceExtensions.cs index 79d80e13..8d618973 100644 --- a/src/order-service/src/Orders.Api/TraceExtensions.cs +++ b/src/order-service/src/Orders.Api/TraceExtensions.cs @@ -3,8 +3,7 @@ // Copyright 2025 Datadog, Inc. using Datadog.Trace; -using Orders.Api.CompleteOrder; -using Orders.Api.CreateOrder; +using Orders.Api.Models; namespace Orders.Api; diff --git a/src/order-service/src/Orders.Api/V1/Models/OrderDtoV1.cs b/src/order-service/src/Orders.Api/V1/Models/OrderDtoV1.cs new file mode 100644 index 00000000..741b4a5a --- /dev/null +++ b/src/order-service/src/Orders.Api/V1/Models/OrderDtoV1.cs @@ -0,0 +1,75 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +using Orders.Core; + +namespace Orders.Api.V1.Models; + +/// +/// Version 1 of the Order DTO - maintains backward compatibility +/// +public record OrderDtoV1( + string OrderId, + string UserId, + IReadOnlyList Products, + DateTime OrderDate, + string OrderType, + string OrderStatus, + decimal TotalPrice) +{ + /// + /// Creates a V1 DTO from a domain Order object + /// + public static OrderDtoV1 FromOrder(Order order) + { + return new OrderDtoV1( + order.OrderNumber, + order.UserId, + order.Products, + order.OrderDate, + order.OrderType.ToString(), + order.OrderStatus.ToString(), + order.TotalPrice + ); + } +} + +/// +/// Version 1 paginated response format +/// +/// The type of items in the response +public record PaginatedResponseV1( + IReadOnlyList Data, + int PageSize, + bool HasMorePages, + string? NextPageToken) +{ + /// + /// Gets the total number of items in the current page + /// + public int Count => Data.Count; +} + +/// +/// Version 1 API response envelope for consistent error handling +/// +public record ApiResponseV1( + T? Data, + bool Success, + string? Error = null, + string? CorrelationId = null, + int? ErrorCode = null) +{ + /// + /// Creates a successful response + /// + public static ApiResponseV1 Ok(T data, string? correlationId = null) => + new(data, true, null, correlationId, null); + + /// + /// Creates an error response + /// + public static ApiResponseV1 Failure(string error, string? correlationId = null, int? errorCode = null) => + new(default, false, error, correlationId, errorCode); +} \ No newline at end of file diff --git a/src/order-service/src/Orders.Api/Versioning/ApiDeprecationMiddleware.cs b/src/order-service/src/Orders.Api/Versioning/ApiDeprecationMiddleware.cs new file mode 100644 index 00000000..263af481 --- /dev/null +++ b/src/order-service/src/Orders.Api/Versioning/ApiDeprecationMiddleware.cs @@ -0,0 +1,103 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +using Asp.Versioning; +using Orders.Api.Logging; + +namespace Orders.Api.Versioning; + +/// +/// Middleware to handle API version deprecation warnings and sunset notifications +/// +public class ApiDeprecationMiddleware +{ + private readonly RequestDelegate _next; + private readonly ILogger _logger; + + public ApiDeprecationMiddleware(RequestDelegate next, ILogger logger) + { + _next = next ?? throw new ArgumentNullException(nameof(next)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } + + public async Task InvokeAsync(HttpContext context) + { + var correlationId = context.Items["CorrelationId"]?.ToString() ?? Guid.NewGuid().ToString(); + + try + { + // Get the requested API version + var apiVersion = context.GetRequestedApiVersion(); + var userClaims = context.User?.Claims?.ExtractUserId(); + var userType = userClaims?.UserType ?? "ANONYMOUS"; + var endpoint = context.Request.Path.ToString().Replace("\r", "").Replace("\n", ""); + + if (apiVersion != null) + { + // Check for deprecated versions + if (apiVersion.MajorVersion == 1 && apiVersion.MinorVersion == 0) + { + // V1.0 is currently stable but will be deprecated in future + // Add headers to inform clients about future deprecation + context.Response.Headers["X-API-Version"] = apiVersion.ToString(); + context.Response.Headers["X-API-Supported-Versions"] = "1.0"; + context.Response.Headers["X-API-Latest-Version"] = "1.0"; + + // Log API version usage for analytics (NO PII) + _logger.LogInformation("API version {ApiVersion} accessed by user type {UserType} at sanitized endpoint {Endpoint}", + apiVersion.ToString(), userType, endpoint); + } + + // Future: When V2 is available and V1 becomes deprecated + /* + if (apiVersion.MajorVersion == 1) + { + context.Response.Headers.Add("X-API-Deprecated", "true"); + context.Response.Headers.Add("X-API-Sunset", "2025-12-31"); + context.Response.Headers.Add("X-API-Deprecation-Info", "API v1 is deprecated. Please migrate to v2 by December 31, 2025."); + context.Response.Headers.Add("X-API-Migration-Guide", "https://docs.example.com/api/v2/migration"); + + _logger.LogWarning("Deprecated API version {ApiVersion} accessed by user type {UserType} at endpoint {Endpoint}", + apiVersion.ToString(), userType, endpoint); + } + */ + + // Add standard versioning headers + context.Response.Headers["X-API-Current-Version"] = apiVersion.ToString(); + } + else + { + // No version specified - using default + context.Response.Headers["X-API-Version"] = "1.0"; + context.Response.Headers["X-API-Default-Version"] = "true"; + + _logger.LogInformation("Default API version used by user type {UserType} at sanitized endpoint {Endpoint}", + userType, endpoint); + } + + await _next(context); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error in API deprecation middleware for correlation {CorrelationId}", correlationId); + + // Don't block the request if middleware fails + await _next(context); + } + } +} + +/// +/// Extension methods for API deprecation middleware +/// +public static class ApiDeprecationMiddlewareExtensions +{ + /// + /// Adds API deprecation middleware to the pipeline + /// + public static IApplicationBuilder UseApiDeprecation(this IApplicationBuilder builder) + { + return builder.UseMiddleware(); + } +} \ No newline at end of file diff --git a/src/order-service/src/Orders.Core/Adapters/DynamoDBOrders.cs b/src/order-service/src/Orders.Core/Adapters/DynamoDBOrders.cs index 24e49038..225ef040 100644 --- a/src/order-service/src/Orders.Core/Adapters/DynamoDBOrders.cs +++ b/src/order-service/src/Orders.Core/Adapters/DynamoDBOrders.cs @@ -3,12 +3,15 @@ // Copyright 2025 Datadog, Inc. using System.Globalization; +using System.Text.Json; using Amazon.DynamoDBv2; using Amazon.DynamoDBv2.Model; using Datadog.Trace; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; +using Orders.Core.Common; using Polly; +using System.Diagnostics; namespace Orders.Core.Adapters; @@ -42,8 +45,11 @@ public class DynamoDBOrders( private readonly ResiliencePipeline _batchWriteResiliencePipeline = ResiliencePolicies.GetDynamoDBPolicy(logger); - public async Task> ForUser(string userId, int pageSize = PAGE_SIZE, string? lastEvaluatedKey = null) + public async Task> ForUser(string userId, PaginationRequest pagination, CancellationToken cancellationToken = default) { + var stopwatch = Stopwatch.StartNew(); + logger.LogDebug("Starting DynamoDB query for user orders with page size {PageSize}", pagination.PageSize); + var queryRequest = new QueryRequest() { TableName = configuration["TABLE_NAME"], @@ -52,24 +58,25 @@ public async Task> ForUser(string userId, int pageSize = PAGE_SIZE, { { ":PK", new AttributeValue { S = userId } } }, - Limit = pageSize, + Limit = pagination.PageSize, ReturnConsumedCapacity = ReturnConsumedCapacity.TOTAL }; - if (!string.IsNullOrEmpty(lastEvaluatedKey)) + if (!string.IsNullOrEmpty(pagination.PageToken)) { - queryRequest.ExclusiveStartKey = new Dictionary + var exclusiveStartKey = ParsePageToken(pagination.PageToken); + if (exclusiveStartKey != null) { - { PARTITION_KEY, new AttributeValue { S = userId } }, - { SORT_KEY, new AttributeValue { S = lastEvaluatedKey } } - }; + queryRequest.ExclusiveStartKey = exclusiveStartKey; + } } var queryResult = await _queryResiliencePipeline.ExecuteAsync( async ct => await dynamoDbClient.QueryAsync(queryRequest, ct), - CancellationToken.None); + cancellationToken); queryResult.AddToTelemetry(); + stopwatch.Stop(); var orderList = new List(); @@ -83,10 +90,24 @@ public async Task> ForUser(string userId, int pageSize = PAGE_SIZE, item[PRODUCTS].SS.ToArray(), (OrderStatus)Enum.ToObject(typeof(OrderStatus), int.Parse(item[ORDER_STATUS].N)))); - return orderList; + // Create page token for next page if there are more results + var nextPageToken = queryResult.LastEvaluatedKey?.Any() == true + ? CreatePageToken(queryResult.LastEvaluatedKey) + : null; + + var hasMorePages = queryResult.LastEvaluatedKey?.Any() == true; + + logger.LogInformation("DynamoDB query completed: returned {ItemCount} orders in {DurationMs}ms, consumed {ConsumedCapacity} RCU", + orderList.Count, stopwatch.ElapsedMilliseconds, queryResult.ConsumedCapacity?.CapacityUnits ?? 0); + + return new PagedResult( + orderList.AsReadOnly(), + pagination.PageSize, + nextPageToken, + hasMorePages); } - public async Task> ConfirmedOrders(int pageSize = PAGE_SIZE, string? lastEvaluatedKey = null) + public async Task> ConfirmedOrders(PaginationRequest pagination, CancellationToken cancellationToken = default) { var queryRequest = new QueryRequest() { @@ -97,22 +118,22 @@ public async Task> ConfirmedOrders(int pageSize = PAGE_SIZE, string? { ":PK", new AttributeValue { S = "CONFIRMED" } } }, IndexName = "GSI1", - Limit = pageSize, + Limit = pagination.PageSize, ReturnConsumedCapacity = ReturnConsumedCapacity.TOTAL }; - if (!string.IsNullOrEmpty(lastEvaluatedKey)) + if (!string.IsNullOrEmpty(pagination.PageToken)) { - queryRequest.ExclusiveStartKey = new Dictionary + var exclusiveStartKey = ParsePageTokenForGSI(pagination.PageToken); + if (exclusiveStartKey != null) { - { GSI1PK, new AttributeValue { S = "CONFIRMED" } }, - { GSI1SK, new AttributeValue { S = lastEvaluatedKey } } - }; + queryRequest.ExclusiveStartKey = exclusiveStartKey; + } } var queryResult = await _queryResiliencePipeline.ExecuteAsync( async ct => await dynamoDbClient.QueryAsync(queryRequest, ct), - CancellationToken.None); + cancellationToken); queryResult.AddToTelemetry(); @@ -128,10 +149,21 @@ public async Task> ConfirmedOrders(int pageSize = PAGE_SIZE, string? item[PRODUCTS].SS.ToArray(), (OrderStatus)Enum.ToObject(typeof(OrderStatus), int.Parse(item[ORDER_STATUS].N)))); - return orderList; + // Create page token for next page if there are more results + var nextPageToken = queryResult.LastEvaluatedKey?.Any() == true + ? CreatePageTokenForGSI(queryResult.LastEvaluatedKey) + : null; + + var hasMorePages = queryResult.LastEvaluatedKey?.Any() == true; + + return new PagedResult( + orderList.AsReadOnly(), + pagination.PageSize, + nextPageToken, + hasMorePages); } - public async Task WithOrderId(string userId, string orderId) + public async Task WithOrderId(string userId, string orderId, CancellationToken cancellationToken = default) { logger.LogInformation("Retrieving Order with orderId {orderId} and user {userId} from DynamoDB", orderId, userId); @@ -149,7 +181,7 @@ public async Task> ConfirmedOrders(int pageSize = PAGE_SIZE, string? var getItemResult = await _getItemResiliencePipeline.ExecuteAsync( async ct => await dynamoDbClient.GetItemAsync(getItemRequest, ct), - CancellationToken.None); + cancellationToken); getItemResult.AddToTelemetry(); @@ -165,9 +197,10 @@ public async Task> ConfirmedOrders(int pageSize = PAGE_SIZE, string? (OrderStatus)Enum.ToObject(typeof(OrderStatus), int.Parse(getItemResult.Item[ORDER_STATUS].N))); } - public async Task Store(Order order) + public async Task Store(Order order, CancellationToken cancellationToken = default) { - logger.LogInformation("Updating Order with orderNumber {orderId}", order.OrderNumber); + var stopwatch = Stopwatch.StartNew(); + logger.LogDebug("Starting DynamoDB store operation for order type {OrderType}", order.OrderType.ToString()); var attributes = new Dictionary() { { PARTITION_KEY, new AttributeValue(order.UserId) }, @@ -197,12 +230,16 @@ public async Task Store(Order order) var putItemResponse = await _putItemResiliencePipeline.ExecuteAsync( async ct => await dynamoDbClient.PutItemAsync(putItemRequest, ct), - CancellationToken.None); + cancellationToken); putItemResponse.AddToTelemetry(); + stopwatch.Stop(); + + logger.LogInformation("DynamoDB store completed: order type {OrderType} stored in {DurationMs}ms, consumed {ConsumedCapacity} WCU", + order.OrderType.ToString(), stopwatch.ElapsedMilliseconds, putItemResponse.ConsumedCapacity?.CapacityUnits ?? 0); } - public async Task StoreBatch(IEnumerable orders) + public async Task StoreBatch(IEnumerable orders, CancellationToken cancellationToken = default) { var writeRequests = new List(); @@ -247,7 +284,7 @@ public async Task StoreBatch(IEnumerable orders) var response = await _batchWriteResiliencePipeline.ExecuteAsync( async ct => await dynamoDbClient.BatchWriteItemAsync(batchRequest, ct), - CancellationToken.None); + cancellationToken); // Handle unprocessed items if any if (response.UnprocessedItems.Count > 0 && response.UnprocessedItems.ContainsKey(configuration["TABLE_NAME"])) @@ -261,4 +298,61 @@ public async Task StoreBatch(IEnumerable orders) } } } + + /// + /// Converts DynamoDB LastEvaluatedKey to a page token + /// + private static string CreatePageToken(Dictionary lastEvaluatedKey) + { + var pageTokenData = new Dictionary(); + foreach (var kvp in lastEvaluatedKey) + { + pageTokenData[kvp.Key] = kvp.Value.S ?? kvp.Value.N ?? ""; + } + + var json = JsonSerializer.Serialize(pageTokenData); + return Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(json)); + } + + /// + /// Converts a page token back to DynamoDB LastEvaluatedKey + /// + private static Dictionary? ParsePageToken(string pageToken) + { + try + { + var json = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(pageToken)); + var pageTokenData = JsonSerializer.Deserialize>(json); + + if (pageTokenData == null) return null; + + var lastEvaluatedKey = new Dictionary(); + foreach (var kvp in pageTokenData) + { + lastEvaluatedKey[kvp.Key] = new AttributeValue { S = kvp.Value }; + } + + return lastEvaluatedKey; + } + catch + { + return null; // Invalid token, ignore + } + } + + /// + /// Creates a page token for GSI queries + /// + private static string CreatePageTokenForGSI(Dictionary lastEvaluatedKey) + { + return CreatePageToken(lastEvaluatedKey); // Same implementation for now + } + + /// + /// Parses a page token for GSI queries + /// + private static Dictionary? ParsePageTokenForGSI(string pageToken) + { + return ParsePageToken(pageToken); // Same implementation for now + } } \ No newline at end of file diff --git a/src/order-service/src/Orders.Core/Common/PaginationModels.cs b/src/order-service/src/Orders.Core/Common/PaginationModels.cs new file mode 100644 index 00000000..00cd72c3 --- /dev/null +++ b/src/order-service/src/Orders.Core/Common/PaginationModels.cs @@ -0,0 +1,52 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +namespace Orders.Core.Common; + +/// +/// Represents a request for paginated data +/// +public record PaginationRequest( + int PageSize = 20, + string? PageToken = null) +{ + /// + /// Validates the pagination request parameters + /// + public bool IsValid => PageSize > 0 && PageSize <= 100; +} + +/// +/// Represents a paginated result set +/// +/// The type of items in the result set +public record PagedResult( + IReadOnlyList Items, + int PageSize, + string? NextPageToken, + bool HasMorePages) +{ + /// + /// Gets the number of items in the current page + /// + public int ItemCount => Items.Count; + + /// + /// Creates an empty paged result + /// + public static PagedResult Empty(int pageSize) => + new(Array.Empty(), pageSize, null, false); + + /// + /// Creates a paged result for a single page with no more data + /// + public static PagedResult SinglePage(IReadOnlyList items, int pageSize) => + new(items, pageSize, null, false); + + /// + /// Creates a paged result with a continuation token for more data + /// + public static PagedResult WithNextPage(IReadOnlyList items, int pageSize, string nextPageToken) => + new(items, pageSize, nextPageToken, true); +} \ No newline at end of file diff --git a/src/order-service/src/Orders.Core/Common/Result.cs b/src/order-service/src/Orders.Core/Common/Result.cs new file mode 100644 index 00000000..3249b404 --- /dev/null +++ b/src/order-service/src/Orders.Core/Common/Result.cs @@ -0,0 +1,85 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +namespace Orders.Core.Common; + +/// +/// Represents the result of an operation that can either succeed or fail +/// +public abstract record Result +{ + public abstract bool IsSuccess { get; } + public bool IsFailure => !IsSuccess; +} + +/// +/// Represents a successful result with a value +/// +public sealed record Success(T Value) : Result +{ + public override bool IsSuccess => true; +} + +/// +/// Represents a failed result with error information +/// +public sealed record Failure(string ErrorCode, string ErrorMessage, Exception? Exception = null) : Result +{ + public override bool IsSuccess => false; +} + +/// +/// Extension methods for working with Result types +/// +public static class ResultExtensions +{ + public static Result Success(T value) => new Success(value); + + public static Result Failure(string errorCode, string errorMessage, Exception? exception = null) => + new Failure(errorCode, errorMessage, exception); + + public static Result Map(this Result result, Func mapper) + { + return result switch + { + Success success => Success(mapper(success.Value)), + Failure failure => Failure(failure.ErrorCode, failure.ErrorMessage, failure.Exception), + _ => throw new InvalidOperationException("Unknown result type") + }; + } + + public static async Task> MapAsync( + this Result result, + Func> mapper) + { + return result switch + { + Success success => Success(await mapper(success.Value)), + Failure failure => Failure(failure.ErrorCode, failure.ErrorMessage, failure.Exception), + _ => throw new InvalidOperationException("Unknown result type") + }; + } + + public static Result FlatMap(this Result result, Func> mapper) + { + return result switch + { + Success success => mapper(success.Value), + Failure failure => Failure(failure.ErrorCode, failure.ErrorMessage, failure.Exception), + _ => throw new InvalidOperationException("Unknown result type") + }; + } + + public static async Task> FlatMapAsync( + this Result result, + Func>> mapper) + { + return result switch + { + Success success => await mapper(success.Value), + Failure failure => Failure(failure.ErrorCode, failure.ErrorMessage, failure.Exception), + _ => throw new InvalidOperationException("Unknown result type") + }; + } +} \ No newline at end of file diff --git a/src/order-service/src/Orders.Core/Domain/Exceptions/OrderNotFoundException.cs b/src/order-service/src/Orders.Core/Domain/Exceptions/OrderNotFoundException.cs new file mode 100644 index 00000000..87ffed5c --- /dev/null +++ b/src/order-service/src/Orders.Core/Domain/Exceptions/OrderNotFoundException.cs @@ -0,0 +1,30 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +using Orders.Core.Domain.Models; + +namespace Orders.Core.Domain.Exceptions; + +/// +/// Exception thrown when an order cannot be found +/// +public class OrderNotFoundException : Exception +{ + public OrderId OrderId { get; } + public UserId UserId { get; } + + public OrderNotFoundException(OrderId orderId, UserId userId) + : base($"Order with ID '{orderId.Value}' not found for user '{userId.Value}'") + { + OrderId = orderId; + UserId = userId; + } + + public OrderNotFoundException(OrderId orderId, UserId userId, Exception innerException) + : base($"Order with ID '{orderId.Value}' not found for user '{userId.Value}'", innerException) + { + OrderId = orderId; + UserId = userId; + } +} \ No newline at end of file diff --git a/src/order-service/src/Orders.Core/Domain/Exceptions/OrderValidationException.cs b/src/order-service/src/Orders.Core/Domain/Exceptions/OrderValidationException.cs new file mode 100644 index 00000000..6d113ed6 --- /dev/null +++ b/src/order-service/src/Orders.Core/Domain/Exceptions/OrderValidationException.cs @@ -0,0 +1,28 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +namespace Orders.Core.Domain.Exceptions; + +/// +/// Exception thrown when order validation fails +/// +public class OrderValidationException : Exception +{ + public Dictionary ValidationErrors { get; } + + public OrderValidationException(string message) : base(message) + { + ValidationErrors = new Dictionary(); + } + + public OrderValidationException(string message, Dictionary validationErrors) : base(message) + { + ValidationErrors = validationErrors; + } + + public OrderValidationException(string message, Exception innerException) : base(message, innerException) + { + ValidationErrors = new Dictionary(); + } +} \ No newline at end of file diff --git a/src/order-service/src/Orders.Core/Domain/Exceptions/WorkflowException.cs b/src/order-service/src/Orders.Core/Domain/Exceptions/WorkflowException.cs new file mode 100644 index 00000000..ddf730cd --- /dev/null +++ b/src/order-service/src/Orders.Core/Domain/Exceptions/WorkflowException.cs @@ -0,0 +1,25 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +using Orders.Core.Domain.Models; + +namespace Orders.Core.Domain.Exceptions; + +/// +/// Exception thrown when workflow operations fail +/// +public class WorkflowException : Exception +{ + public OrderId OrderId { get; } + + public WorkflowException(OrderId orderId, string message) : base(message) + { + OrderId = orderId; + } + + public WorkflowException(OrderId orderId, string message, Exception innerException) : base(message, innerException) + { + OrderId = orderId; + } +} \ No newline at end of file diff --git a/src/order-service/src/Orders.Core/IOrders.cs b/src/order-service/src/Orders.Core/IOrders.cs index 1e99dd30..847450a0 100644 --- a/src/order-service/src/Orders.Core/IOrders.cs +++ b/src/order-service/src/Orders.Core/IOrders.cs @@ -2,17 +2,52 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2025 Datadog, Inc. +using Orders.Core.Common; + namespace Orders.Core; +/// +/// Repository interface for order data access operations +/// public interface IOrders { - Task> ForUser(string userId, int pageSize = 20, string? lastEvaluatedKey = null); + /// + /// Gets orders for a specific user with pagination + /// + /// The user ID to get orders for + /// Pagination parameters + /// Cancellation token + /// Paginated list of orders for the user + Task> ForUser(string userId, PaginationRequest pagination, CancellationToken cancellationToken = default); - Task> ConfirmedOrders(int pageSize = 20, string? lastEvaluatedKey = null); + /// + /// Gets all confirmed orders with pagination + /// + /// Pagination parameters + /// Cancellation token + /// Paginated list of confirmed orders + Task> ConfirmedOrders(PaginationRequest pagination, CancellationToken cancellationToken = default); - Task WithOrderId(string userId, string orderNumber); + /// + /// Gets a specific order by user ID and order ID + /// + /// The user ID that owns the order + /// The order number/ID + /// Cancellation token + /// The order if found, null otherwise + Task WithOrderId(string userId, string orderNumber, CancellationToken cancellationToken = default); - Task Store(Order item); + /// + /// Stores a single order + /// + /// The order to store + /// Cancellation token + Task Store(Order item, CancellationToken cancellationToken = default); - Task StoreBatch(IEnumerable orders); + /// + /// Stores multiple orders in a batch operation + /// + /// The orders to store + /// Cancellation token + Task StoreBatch(IEnumerable orders, CancellationToken cancellationToken = default); } \ No newline at end of file diff --git a/src/order-service/src/Orders.IntegrationTests/ApiIntegrationTests.cs b/src/order-service/src/Orders.IntegrationTests/ApiIntegrationTests.cs index 3a678f36..6d4e72d1 100644 --- a/src/order-service/src/Orders.IntegrationTests/ApiIntegrationTests.cs +++ b/src/order-service/src/Orders.IntegrationTests/ApiIntegrationTests.cs @@ -11,6 +11,13 @@ public class ApiIntegrationTests private readonly ITestOutputHelper _outputHelper; private readonly ApiDriver _apiDriver; + private readonly JsonSerializerOptions options = new() + { + PropertyNameCaseInsensitive = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull + }; + public ApiIntegrationTests(ITestOutputHelper outputHelper) { _outputHelper = outputHelper; @@ -25,7 +32,7 @@ public async Task WhenUserIsValid_CanCreateOrder() Assert.True(createOrderResult.IsSuccessStatusCode); - var order = JsonSerializer.Deserialize(await createOrderResult.Content.ReadAsStringAsync()); + var order = JsonSerializer.Deserialize(await createOrderResult.Content.ReadAsStringAsync(), options); var orderCreatedWasPublished = await _apiDriver.VerifyEventPublishedFor(order.OrderId, "orders.orderCreated.v1"); @@ -40,7 +47,7 @@ public async Task WhenUserIsValid_CanCreateOrder() getOrderResult = await _apiDriver.GetOrderDetailsFor(order.OrderId); - order = JsonSerializer.Deserialize(await getOrderResult.Content.ReadAsStringAsync()); + order = JsonSerializer.Deserialize(await getOrderResult.Content.ReadAsStringAsync(), options); Assert.Equal("Confirmed", order.OrderStatus); @@ -59,7 +66,7 @@ public async Task WhenOutOfStockEventReceived_OrderSetToNoStock() Assert.True(createOrderResult.IsSuccessStatusCode); - var order = JsonSerializer.Deserialize(await createOrderResult.Content.ReadAsStringAsync()); + var order = JsonSerializer.Deserialize(await createOrderResult.Content.ReadAsStringAsync(), options); var getOrderResult = await _apiDriver.GetOrderDetailsFor(order.OrderId); @@ -70,7 +77,7 @@ public async Task WhenOutOfStockEventReceived_OrderSetToNoStock() getOrderResult = await _apiDriver.GetOrderDetailsFor(order.OrderId); - order = JsonSerializer.Deserialize(await getOrderResult.Content.ReadAsStringAsync()); + order = JsonSerializer.Deserialize(await getOrderResult.Content.ReadAsStringAsync(), options); Assert.Equal("NoStock", order.OrderStatus); } @@ -84,10 +91,10 @@ public async Task WhenUserIsValid_CanCreateAndCompleteOrder() Assert.True(createOrderResult.IsSuccessStatusCode); - var order = JsonSerializer.Deserialize(await createOrderResult.Content.ReadAsStringAsync()); + var order = JsonSerializer.Deserialize(await createOrderResult.Content.ReadAsStringAsync(), options); var getOrderResult = await _apiDriver.GetOrderDetailsFor(order.OrderId); - order = JsonSerializer.Deserialize(await getOrderResult.Content.ReadAsStringAsync()); + order = JsonSerializer.Deserialize(await getOrderResult.Content.ReadAsStringAsync(), options); await _apiDriver.StockReservationSuccessfulFor(order.OrderId); @@ -97,9 +104,9 @@ public async Task WhenUserIsValid_CanCreateAndCompleteOrder() _outputHelper.WriteLine($"List confirmed order response was {response}"); var confirmedOrders = - JsonSerializer.Deserialize>(response); + JsonSerializer.Deserialize>(response, options); - Assert.Contains(confirmedOrders, o => o.OrderId == order.OrderId); + Assert.Contains(confirmedOrders.Items, o => o.OrderId == order.OrderId); await _apiDriver.OrderCompleted(order.OrderId, order.UserId); @@ -115,7 +122,7 @@ public async Task IfNoStockReservationResponseReceived_ShouldRetryPublishOfOrder Assert.True(createOrderResult.IsSuccessStatusCode); - var order = JsonSerializer.Deserialize(await createOrderResult.Content.ReadAsStringAsync()); + var order = JsonSerializer.Deserialize(await createOrderResult.Content.ReadAsStringAsync(), options); var getOrderResult = await _apiDriver.GetOrderDetailsFor(order.OrderId); @@ -133,7 +140,7 @@ public async Task IfNoStockReservationResponseReceived_ShouldRetryPublishOfOrder getOrderResult = await _apiDriver.GetOrderDetailsFor(order.OrderId); - order = JsonSerializer.Deserialize(await getOrderResult.Content.ReadAsStringAsync()); + order = JsonSerializer.Deserialize(await getOrderResult.Content.ReadAsStringAsync(), options); Assert.Equal("Confirmed", order.OrderStatus); } diff --git a/src/order-service/src/Orders.Api/CreateOrder/CreateOrderRequest.cs b/src/order-service/src/Orders.IntegrationTests/PagedResponse.cs similarity index 50% rename from src/order-service/src/Orders.Api/CreateOrder/CreateOrderRequest.cs rename to src/order-service/src/Orders.IntegrationTests/PagedResponse.cs index a1cbfd3e..1cbd31dc 100644 --- a/src/order-service/src/Orders.Api/CreateOrder/CreateOrderRequest.cs +++ b/src/order-service/src/Orders.IntegrationTests/PagedResponse.cs @@ -2,12 +2,12 @@ // This product includes software developed at Datadog (https://www.datadoghq.com/). // Copyright 2025 Datadog, Inc. -using System.Text.Json.Serialization; +namespace Orders.IntegrationTests; -namespace Orders.Api.CreateOrder; - -public record CreateOrderRequest +public record PagedResponse { - [JsonPropertyName("products")] - public string[] Products { get; set; } = []; + public List Items { get; set; } + public int PageSize { get; set; } + public bool HasMorePages { get; set; } + public string NextPageToken { get; set; } } \ No newline at end of file diff --git a/src/order-service/src/Orders.UnitTests/Api/ErrorHandlingTests.cs b/src/order-service/src/Orders.UnitTests/Api/ErrorHandlingTests.cs new file mode 100644 index 00000000..5243f6e8 --- /dev/null +++ b/src/order-service/src/Orders.UnitTests/Api/ErrorHandlingTests.cs @@ -0,0 +1,143 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2025 Datadog, Inc. + +using System.Text.Json; +using Orders.Api.Models; +using Orders.Core.Common; + +namespace Orders.UnitTests.Api; + +public class ErrorHandlingTests +{ + [Fact] + public void ErrorResponse_SerializesToJson_WithCorrectFormat() + { + // Arrange + var errorResponse = new ErrorResponse( + ErrorCodes.ValidationError, + "Test error message", + "Test details", + new Dictionary + { + ["field1"] = new[] { "error1", "error2" }, + ["field2"] = new[] { "error3" } + }, + "test-correlation-id" + ); + + // Act + var json = JsonSerializer.Serialize(errorResponse, new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }); + + // Assert + json.Should().Contain("\"error\":\"VALIDATION_ERROR\""); + json.Should().Contain("\"message\":\"Test error message\""); + json.Should().Contain("\"details\":\"Test details\""); + json.Should().Contain("\"correlationId\":\"test-correlation-id\""); + json.Should().Contain("\"validationErrors\""); + } + + [Fact] + public void ValidationErrorResponse_SerializesToJson_WithCorrectFormat() + { + // Arrange + var validationErrors = new Dictionary + { + ["Products"] = new[] { "At least one product must be specified" }, + ["UserId"] = new[] { "User ID is required" } + }; + + var errorResponse = new ValidationErrorResponse( + ErrorCodes.ValidationError, + validationErrors, + "test-correlation-id" + ); + + // Act + var json = JsonSerializer.Serialize(errorResponse, new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }); + + // Assert + json.Should().Contain("\"error\":\"VALIDATION_ERROR\""); + json.Should().Contain("\"correlationId\":\"test-correlation-id\""); + json.Should().Contain("\"validationErrors\""); + json.Should().Contain("\"Products\""); + json.Should().Contain("\"UserId\""); + } + + [Fact] + public void Result_Success_HasCorrectProperties() + { + // Arrange + var value = "test-value"; + + // Act + var result = ResultExtensions.Success(value); + + // Assert + result.IsSuccess.Should().BeTrue(); + result.IsFailure.Should().BeFalse(); + result.Should().BeOfType>(); + var success = result as Success; + success!.Value.Should().Be(value); + } + + [Fact] + public void Result_Failure_HasCorrectProperties() + { + // Arrange + var errorCode = ErrorCodes.ValidationError; + var errorMessage = "Test error"; + var exception = new ArgumentException("Test exception"); + + // Act + var result = ResultExtensions.Failure(errorCode, errorMessage, exception); + + // Assert + result.IsSuccess.Should().BeFalse(); + result.IsFailure.Should().BeTrue(); + result.Should().BeOfType>(); + var failure = result as Failure; + failure!.ErrorCode.Should().Be(errorCode); + failure.ErrorMessage.Should().Be(errorMessage); + failure.Exception.Should().Be(exception); + } + + [Fact] + public void Result_Map_TransformsSuccessValue() + { + // Arrange + var originalResult = ResultExtensions.Success(5); + + // Act + var mappedResult = originalResult.Map(x => x.ToString()); + + // Assert + mappedResult.IsSuccess.Should().BeTrue(); + mappedResult.Should().BeOfType>(); + var success = mappedResult as Success; + success!.Value.Should().Be("5"); + } + + [Fact] + public void Result_Map_PreservesFailure() + { + // Arrange + var originalResult = ResultExtensions.Failure(ErrorCodes.ValidationError, "Test error"); + + // Act + var mappedResult = originalResult.Map(x => x.ToString()); + + // Assert + mappedResult.IsFailure.Should().BeTrue(); + mappedResult.Should().BeOfType>(); + var failure = mappedResult as Failure; + failure!.ErrorCode.Should().Be(ErrorCodes.ValidationError); + failure.ErrorMessage.Should().Be("Test error"); + } +} \ No newline at end of file diff --git a/src/order-service/src/Orders.UnitTests/Orders.UnitTests.csproj b/src/order-service/src/Orders.UnitTests/Orders.UnitTests.csproj index bf828388..b34848ea 100644 --- a/src/order-service/src/Orders.UnitTests/Orders.UnitTests.csproj +++ b/src/order-service/src/Orders.UnitTests/Orders.UnitTests.csproj @@ -37,6 +37,7 @@ + From 478171280fb5132fccc1c321b7f3d379a9ce76b2 Mon Sep 17 00:00:00 2001 From: James Eastham Date: Tue, 1 Jul 2025 15:59:26 +0100 Subject: [PATCH 2/6] feat: add SAM and TF example * feat: add SAM template * chore: readd TF and SAM to analytics workflow * feat: add Terraform example to activity service: * chore: add AWS_DEFAULT_REGION to Python integration tests * fix: add dev env setup to GH action * chore: temporarily remove TF tests * fix: update role name to include Iac prefix * feat:bump layer versions --- .github/workflows/deploy-activity-service.yml | 236 +-- src/activity-service/CLAUDE.md | 1586 ++++++++++++++++- src/activity-service/Makefile | 31 +- .../cdk/activity_service/api_construct.py | 2 +- src/activity-service/dev_requirements.txt | 24 +- .../infra/.terraform.lock.hcl | 25 + src/activity-service/infra/main.tf | 24 + .../modules/api-gateway-cors-resource/main.tf | 56 + .../api-gateway-cors-resource/output.tf | 18 + .../api-gateway-cors-resource/variables.tf | 20 + .../api-gateway-lambda-integration/data.tf | 2 + .../api-gateway-lambda-integration/main.tf | 30 + .../variables.tf | 46 + .../infra/modules/api-gateway/main.tf | 14 + .../infra/modules/api-gateway/output.tf | 18 + .../infra/modules/api-gateway/variables.tf | 26 + .../infra/modules/lambda-function/main.tf | 121 ++ .../infra/modules/lambda-function/output.tf | 29 + .../modules/lambda-function/variables.tf | 66 + .../modules/python-lambda-function/main.tf | 134 ++ .../modules/python-lambda-function/output.tf | 33 + .../python-lambda-function/variables.tf | 83 + .../modules/shared_bus_to_domain/main.tf | 105 ++ .../modules/shared_bus_to_domain/variables.tf | 60 + .../infra/modules/web-service/data.tf | 7 + .../infra/modules/web-service/main.tf | 144 ++ .../infra/modules/web-service/variables.tf | 78 + src/activity-service/infra/outputs.tf | 26 + src/activity-service/infra/providers.tf | 20 + .../infra/services/activity/application.tf | 186 ++ .../infra/services/activity/database.tf | 65 + .../infra/services/activity/events.tf | 214 +++ .../infra/services/activity/iam.tf | 212 +++ .../infra/services/activity/outputs.tf | 66 + .../infra/services/activity/variables.tf | 28 + src/activity-service/infra/variables.tf | 38 + src/activity-service/lambda_requirements.txt | 142 +- src/activity-service/poetry.lock | 162 +- src/activity-service/pyproject.toml | 8 +- src/activity-service/template.yaml | 604 +++++++ 40 files changed, 4498 insertions(+), 291 deletions(-) create mode 100644 src/activity-service/infra/.terraform.lock.hcl create mode 100644 src/activity-service/infra/main.tf create mode 100644 src/activity-service/infra/modules/api-gateway-cors-resource/main.tf create mode 100644 src/activity-service/infra/modules/api-gateway-cors-resource/output.tf create mode 100644 src/activity-service/infra/modules/api-gateway-cors-resource/variables.tf create mode 100644 src/activity-service/infra/modules/api-gateway-lambda-integration/data.tf create mode 100644 src/activity-service/infra/modules/api-gateway-lambda-integration/main.tf create mode 100644 src/activity-service/infra/modules/api-gateway-lambda-integration/variables.tf create mode 100644 src/activity-service/infra/modules/api-gateway/main.tf create mode 100644 src/activity-service/infra/modules/api-gateway/output.tf create mode 100644 src/activity-service/infra/modules/api-gateway/variables.tf create mode 100644 src/activity-service/infra/modules/lambda-function/main.tf create mode 100644 src/activity-service/infra/modules/lambda-function/output.tf create mode 100644 src/activity-service/infra/modules/lambda-function/variables.tf create mode 100644 src/activity-service/infra/modules/python-lambda-function/main.tf create mode 100644 src/activity-service/infra/modules/python-lambda-function/output.tf create mode 100644 src/activity-service/infra/modules/python-lambda-function/variables.tf create mode 100644 src/activity-service/infra/modules/shared_bus_to_domain/main.tf create mode 100644 src/activity-service/infra/modules/shared_bus_to_domain/variables.tf create mode 100644 src/activity-service/infra/modules/web-service/data.tf create mode 100644 src/activity-service/infra/modules/web-service/main.tf create mode 100644 src/activity-service/infra/modules/web-service/variables.tf create mode 100644 src/activity-service/infra/outputs.tf create mode 100644 src/activity-service/infra/providers.tf create mode 100644 src/activity-service/infra/services/activity/application.tf create mode 100644 src/activity-service/infra/services/activity/database.tf create mode 100644 src/activity-service/infra/services/activity/events.tf create mode 100644 src/activity-service/infra/services/activity/iam.tf create mode 100644 src/activity-service/infra/services/activity/outputs.tf create mode 100644 src/activity-service/infra/services/activity/variables.tf create mode 100644 src/activity-service/infra/variables.tf create mode 100644 src/activity-service/template.yaml diff --git a/.github/workflows/deploy-activity-service.yml b/.github/workflows/deploy-activity-service.yml index d15dc095..81a2801b 100644 --- a/.github/workflows/deploy-activity-service.yml +++ b/.github/workflows/deploy-activity-service.yml @@ -40,6 +40,18 @@ jobs: # shell: bash # run: | # echo "sha_short=$(git rev-parse --short "$GITHUB_SHA")" >> "$GITHUB_ENV" + # - name: Setup dev environment + # shell: bash + # env: + # COMMIT_HASH: ${{ env.sha_short }} + # VERSION: ${{ env.sha_short }} + # ENV: "dev" + # DD_API_KEY: ${{secrets.DD_API_KEY}} + # DD_SITE: "datadoghq.eu" + # AWS_REGION: "eu-central-1" + # run: | + # cd src/activity-service + # make dev # - name: Build # shell: bash # env: @@ -73,6 +85,7 @@ jobs: # ENV: ${{ env.sha_short }} # VERSION: ${{ env.sha_short }} # AWS_REGION: "eu-west-2" + # AWS_DEFAULT_REGION: "eu-west-2" # run: | # cd src/activity-service # make integration-test @@ -114,6 +127,7 @@ jobs: # env: # ENV: "dev" # AWS_REGION: "eu-west-2" + # AWS_DEFAULT_REGION: "eu-west-2" # run: | # cd src/activity-service # make integration-test @@ -183,6 +197,7 @@ jobs: ENV: ${{ env.sha_short }} VERSION: ${{ env.sha_short }} AWS_REGION: "eu-west-1" + AWS_DEFAULT_REGION: "eu-west-1" run: | cd src/activity-service make integration-test @@ -216,6 +231,7 @@ jobs: env: ENV: "dev" AWS_REGION: "eu-west-1" + AWS_DEFAULT_REGION: "eu-west-1" run: | cd src/activity-service make integration-test @@ -232,106 +248,120 @@ jobs: cd src/activity-service make cdk-destroy - # deploy-sam: - # runs-on: ubuntu-latest - # steps: - # - name: Check out repository code - # uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - # - name: Install poetry - # run: pipx install poetry - # - name: Set up Python - # uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 - # with: - # python-version: "3.13" - # cache: "poetry" # NOTE: poetry must be installed before this step, or else cache doesn't work - # - uses: aws-actions/setup-sam@v1 - # - name: Configure AWS credentials - # uses: aws-actions/configure-aws-credentials@master - # with: - # role-to-assume: ${{ secrets.AWS_ROLE_ARN }} - # role-session-name: GitHub_to_AWS_via_FederatedOIDC - # aws-region: "eu-central-1" - # - name: Set Commit Hash Environment Variables - # shell: bash - # run: | - # echo "sha_short=$(git rev-parse --short "$GITHUB_SHA")" >> "$GITHUB_ENV" - # - name: Build - # shell: bash - # env: - # COMMIT_HASH: ${{ env.sha_short }} - # VERSION: ${{ env.sha_short }} - # ENV: "dev" - # DD_API_KEY: ${{secrets.DD_API_KEY}} - # DD_SITE: "datadoghq.eu" - # AWS_REGION: "eu-central-1" - # run: | - # cd src/activity-service - # make build - # - name: Deploy to ephermal environment - # shell: bash - # env: - # COMMIT_HASH: ${{ env.sha_short }} - # VERSION: ${{ env.sha_short }} - # ENV: ${{ env.sha_short }} - # DD_API_KEY: ${{secrets.DD_API_KEY}} - # DD_SITE: "datadoghq.eu" - # AWS_REGION: "eu-central-1" - # run: | - # cd src/activity-service - # make sam - # - name: Integration test ephermal environment - # shell: bash - # env: - # ENV: ${{ env.sha_short }} - # VERSION: ${{ env.sha_short }} - # AWS_REGION: "eu-central-1" - # run: | - # cd src/activity-service - # make integration-test - # - name: Destroy - # shell: bash - # if: always() - # env: - # COMMIT_HASH: ${{ env.sha_short }} - # ENV: ${{ env.sha_short }} - # DD_API_KEY: ${{secrets.DD_API_KEY}} - # DD_SITE: "datadoghq.eu" - # AWS_REGION: "eu-central-1" - # run: | - # cd src/activity-service - # make sam-destroy - # - name: Deploy to dev - # if: github.event_name == 'push' - # shell: bash - # env: - # COMMIT_HASH: ${{ env.sha_short }} - # VERSION: ${{ env.sha_short }} - # ENV: "dev" - # DD_API_KEY: ${{secrets.DD_API_KEY}} - # DD_SITE: "datadoghq.eu" - # AWS_REGION: "eu-central-1" - # run: | - # cd src/activity-service - # make sam - # - name: Integration test dev - # if: github.event_name == 'push' - # shell: bash - # env: - # ENV: "dev" - # AWS_REGION: "eu-central-1" - # run: | - # cd src/activity-service - # make integration-test - # - name: Destroy dev - # shell: bash - # if: always() - # env: - # COMMIT_HASH: ${{ env.sha_short }} - # VERSION: ${{ env.sha_short }} - # ENV: "dev" - # DD_API_KEY: ${{secrets.DD_API_KEY}} - # DD_SITE: "datadoghq.eu" - # AWS_REGION: "eu-central-1" - # run: | - # cd src/activity-service - # make sam-destroy + deploy-sam: + runs-on: ubuntu-latest + steps: + - name: Check out repository code + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + - name: Install poetry + run: pipx install poetry + - name: Set up Python + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: "3.13" + cache: "poetry" # NOTE: poetry must be installed before this step, or else cache doesn't work + - uses: aws-actions/setup-sam@v1 + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@master + with: + role-to-assume: ${{ secrets.AWS_ROLE_ARN }} + role-session-name: GitHub_to_AWS_via_FederatedOIDC + aws-region: "eu-central-1" + - name: Set Commit Hash Environment Variables + shell: bash + run: | + echo "sha_short=$(git rev-parse --short "$GITHUB_SHA")" >> "$GITHUB_ENV" + - name: Setup dev environment + shell: bash + env: + COMMIT_HASH: ${{ env.sha_short }} + VERSION: ${{ env.sha_short }} + ENV: "dev" + DD_API_KEY: ${{secrets.DD_API_KEY}} + DD_SITE: "datadoghq.eu" + AWS_REGION: "eu-central-1" + run: | + cd src/activity-service + make dev + - name: Build + shell: bash + env: + COMMIT_HASH: ${{ env.sha_short }} + VERSION: ${{ env.sha_short }} + ENV: "dev" + DD_API_KEY: ${{secrets.DD_API_KEY}} + DD_SITE: "datadoghq.eu" + AWS_REGION: "eu-central-1" + run: | + cd src/activity-service + make build + - name: Deploy to ephermal environment + shell: bash + env: + COMMIT_HASH: ${{ env.sha_short }} + VERSION: ${{ env.sha_short }} + ENV: ${{ env.sha_short }} + DD_API_KEY: ${{secrets.DD_API_KEY}} + DD_SITE: "datadoghq.eu" + AWS_REGION: "eu-central-1" + run: | + cd src/activity-service + make sam + - name: Integration test ephermal environment + shell: bash + env: + ENV: ${{ env.sha_short }} + VERSION: ${{ env.sha_short }} + AWS_REGION: "eu-central-1" + AWS_DEFAULT_REGION: "eu-central-1" + run: | + cd src/activity-service + make integration-test + - name: Destroy + shell: bash + if: always() + env: + COMMIT_HASH: ${{ env.sha_short }} + ENV: ${{ env.sha_short }} + DD_API_KEY: ${{secrets.DD_API_KEY}} + DD_SITE: "datadoghq.eu" + AWS_REGION: "eu-central-1" + run: | + cd src/activity-service + make sam-destroy + - name: Deploy to dev + if: github.event_name == 'push' + shell: bash + env: + COMMIT_HASH: ${{ env.sha_short }} + VERSION: ${{ env.sha_short }} + ENV: "dev" + DD_API_KEY: ${{secrets.DD_API_KEY}} + DD_SITE: "datadoghq.eu" + AWS_REGION: "eu-central-1" + run: | + cd src/activity-service + make sam + - name: Integration test dev + if: github.event_name == 'push' + shell: bash + env: + ENV: "dev" + AWS_REGION: "eu-central-1" + AWS_DEFAULT_REGION: "eu-central-1" + run: | + cd src/activity-service + make integration-test + - name: Destroy dev + shell: bash + if: always() + env: + COMMIT_HASH: ${{ env.sha_short }} + VERSION: ${{ env.sha_short }} + ENV: "dev" + DD_API_KEY: ${{secrets.DD_API_KEY}} + DD_SITE: "datadoghq.eu" + AWS_REGION: "eu-central-1" + run: | + cd src/activity-service + make sam-destroy diff --git a/src/activity-service/CLAUDE.md b/src/activity-service/CLAUDE.md index 04a00db2..e3ea2e8d 100644 --- a/src/activity-service/CLAUDE.md +++ b/src/activity-service/CLAUDE.md @@ -83,21 +83,1571 @@ make pr # Complete pipeline: deps format pre-commit complex lint lint - `e2e/` - End-to-end workflow tests - `infrastructure/` - CDK infrastructure tests -## Development Guidelines - -**Code Quality Tools:** -- Ruff for formatting and linting (line length: 150, Python 3.13) -- MyPy for static type checking -- Pre-commit hooks for automated checks -- CDK NAG for security/compliance scanning - -**Key Files:** -- `app.py` - CDK app entry point -- `pyproject.toml` - Poetry configuration and tool settings -- `Makefile` - Development workflow commands - -**Observability Features:** -- AWS Lambda Powertools integration -- Structured logging and tracing -- CloudWatch monitoring -- X-Ray distributed tracing +## Core Philosophy + +**TEST-DRIVEN DEVELOPMENT IS NON-NEGOTIABLE.** Every single line of production code must be written in response to a failing test. No exceptions. This is not a suggestion or a preference - it is the fundamental practice that enables all other principles in this document. + +I follow Test-Driven Development (TDD) with a strong emphasis on behavior-driven testing and Pythonic programming principles. All work should be done in small, incremental changes that maintain a working state throughout development. + +## Quick Reference + +**Key Principles:** + +- Write tests first (TDD) +- Test behavior, not implementation +- No `Any` types or `# type: ignore` without justification +- Immutable data patterns where appropriate +- Small, pure functions +- Python 3.12+ with strict type checking +- Use real schemas/types in tests, never redefine them +- Follow PEP 8 and modern Python idioms + +**Preferred Tools:** + +- **Language**: Python 3.12+ with type hints +- **Testing**: pytest + hypothesis for property-based testing +- **Type Checking**: mypy in strict mode +- **Linting**: ruff (replaces flake8, isort, black) +- **Schema Validation**: Pydantic v2 for data validation and serialization +- **Package Management**: poetry for dependency management + +## Testing Principles + +### Behavior-Driven Testing + +- **No "unit tests"** - this term is not helpful. Tests should verify expected behavior, treating implementation as a black box +- Test through the public API exclusively - internals should be invisible to tests +- No 1:1 mapping between test files and implementation files +- Tests that examine internal implementation details are wasteful and should be avoided +- **Coverage targets**: 100% coverage should be expected at all times, but these tests must ALWAYS be based on business behaviour, not implementation details +- Tests must document expected business behaviour + +### Testing Tools + +- **pytest** for testing framework with fixtures and parametrization +- **hypothesis** for property-based testing to find edge cases +- **pytest-mock** for mocking when needed (prefer dependency injection) +- **httpx** with respx for HTTP client testing +- All test code must follow the same type checking rules as production code + +### Test Organization + +``` +src/ + features/ + payment/ + payment_processor.py + payment_validator.py + test_payment_processor.py # The validator is an implementation detail. Validation is fully covered, but by testing the expected business behaviour, treating the validation code itself as an implementation detail +``` + +### Test Data Pattern + +Use factory functions with optional overrides for test data, leveraging Pydantic models: + +```python +from typing import Any +from decimal import Decimal +from pydantic import BaseModel + +class AddressDetails(BaseModel): + house_number: str + house_name: str | None = None + address_line_1: str + address_line_2: str | None = None + city: str + postcode: str + +class PayingCardDetails(BaseModel): + cvv: str + token: str + +class PostPaymentsRequestV3(BaseModel): + card_account_id: str + amount: Decimal + source: Literal["Web", "Mobile", "API"] + account_status: Literal["Normal", "Restricted", "Closed"] + last_name: str + date_of_birth: str # Consider using datetime.date with custom validator + paying_card_details: PayingCardDetails + address_details: AddressDetails + brand: Literal["Visa", "Mastercard", "Amex"] + +def get_mock_payment_request( + **overrides: Any, +) -> PostPaymentsRequestV3: + """Factory function for creating test payment requests.""" + base_data = { + "card_account_id": "1234567890123456", + "amount": Decimal("100.00"), + "source": "Web", + "account_status": "Normal", + "last_name": "Doe", + "date_of_birth": "1980-01-01", + "paying_card_details": get_mock_card_details(), + "address_details": get_mock_address_details(), + "brand": "Visa", + } + base_data.update(overrides) + return PostPaymentsRequestV3.model_validate(base_data) + +def get_mock_address_details(**overrides: Any) -> AddressDetails: + """Factory function for creating test address details.""" + base_data = { + "house_number": "123", + "house_name": "Test House", + "address_line_1": "Test Address Line 1", + "address_line_2": "Test Address Line 2", + "city": "Test City", + "postcode": "SW1A 1AA", + } + base_data.update(overrides) + return AddressDetails.model_validate(base_data) + +def get_mock_card_details(**overrides: Any) -> PayingCardDetails: + """Factory function for creating test card details.""" + base_data = { + "cvv": "123", + "token": "test_token_123", + } + base_data.update(overrides) + return PayingCardDetails.model_validate(base_data) +``` + +Key principles: + +- Always return complete objects with sensible defaults +- Accept keyword arguments for overrides using `**overrides` +- Build incrementally - extract nested object factories as needed +- Compose factories for complex objects +- Use Pydantic's `model_validate` to ensure type safety +- Consider using a test data builder pattern with `dataclasses` for very complex objects + +## Python Type System Guidelines + +### Strict Type Checking Requirements + +```toml +# pyproject.toml +[tool.mypy] +python_version = "3.12" +strict = true +warn_return_any = true +warn_unused_configs = true +disallow_untyped_defs = true +disallow_incomplete_defs = true +check_untyped_defs = true +disallow_untyped_decorators = true +no_implicit_optional = true +warn_redundant_casts = true +warn_unused_ignores = true +warn_no_return = true +warn_unreachable = true +strict_equality = true +``` + +- **No `Any`** - ever. Use `object` or proper union types if type is truly unknown +- **No `# type: ignore`** without explicit explanation and issue tracking +- **Use `from __future__ import annotations`** for forward references and cleaner syntax +- These rules apply to test code as well as production code + +### Type Definitions + +- **Use `type` aliases** for complex types and domain-specific types +- Use explicit typing where it aids clarity, but leverage inference where appropriate +- Create NewType for domain-specific types (e.g., `UserId`, `PaymentId`) for type safety +- Use Pydantic models for data validation and serialization +- Prefer `dataclasses` for simple data containers when validation isn't needed + +```python +from __future__ import annotations + +from decimal import Decimal +from typing import NewType +from dataclasses import dataclass +from pydantic import BaseModel, Field + +# Good - Domain-specific types for type safety +UserId = NewType("UserId", str) +PaymentAmount = NewType("PaymentAmount", Decimal) + +# Type aliases for complex types +PaymentResult = dict[str, str | Decimal | bool] +CustomerTier = Literal["standard", "premium", "enterprise"] + +# Avoid - Primitive obsession +def process_payment(user_id: str, amount: Decimal) -> dict[str, Any]: + ... + +# Good - Type safety with NewType +def process_payment(user_id: UserId, amount: PaymentAmount) -> PaymentResult: + ... +``` + +#### Schema-First Development with Pydantic + +Always define your schemas first using Pydantic v2, then derive behavior from them: + +```python +from __future__ import annotations + +from decimal import Decimal +from datetime import datetime +from typing import Literal +from pydantic import BaseModel, Field, field_validator, model_validator +import re + +class AddressDetails(BaseModel): + """Address information for payment processing.""" + house_number: str = Field(min_length=1) + house_name: str | None = None + address_line_1: str = Field(min_length=1) + address_line_2: str | None = None + city: str = Field(min_length=1) + postcode: str + + @field_validator('postcode') + @classmethod + def validate_postcode(cls, v: str) -> str: + pattern = r'^[A-Z]{1,2}\d[A-Z\d]? ?\d[A-Z]{2}$' + if not re.match(pattern, v, re.IGNORECASE): + raise ValueError('Invalid UK postcode format') + return v.upper() + +class PayingCardDetails(BaseModel): + """Card details for payment processing.""" + cvv: str = Field(pattern=r'^\d{3,4}$') + token: str = Field(min_length=1) + +class PostPaymentsRequestV3(BaseModel): + """Request schema for payment processing API v3.""" + card_account_id: str = Field(min_length=16, max_length=16) + amount: Decimal = Field(gt=0, decimal_places=2) + source: Literal["Web", "Mobile", "API"] + account_status: Literal["Normal", "Restricted", "Closed"] + last_name: str = Field(min_length=1) + date_of_birth: str = Field(pattern=r'^\d{4}-\d{2}-\d{2}$') + paying_card_details: PayingCardDetails + address_details: AddressDetails + brand: Literal["Visa", "Mastercard", "Amex"] + + @model_validator(mode='after') + def validate_account_status_with_amount(self) -> PostPaymentsRequestV3: + if self.account_status == "Restricted" and self.amount > Decimal("500"): + raise ValueError("Restricted accounts cannot process payments over £500") + return self + +# Use schemas at runtime boundaries +def parse_payment_request(data: dict[str, Any]) -> PostPaymentsRequestV3: + """Parse and validate payment request data.""" + return PostPaymentsRequestV3.model_validate(data) + +# Example of schema composition for complex domains +class BaseEntity(BaseModel): + """Base model with common fields for all entities.""" + id: str = Field(pattern=r'^[a-f0-9-]{36}$') # UUID format + created_at: datetime + updated_at: datetime + +class Customer(BaseEntity): + """Customer entity with validation.""" + email: str = Field(pattern=r'^[^@]+@[^@]+\.[^@]+$') + tier: CustomerTier + credit_limit: Decimal = Field(gt=0) + + @field_validator('email') + @classmethod + def validate_email_domain(cls, v: str) -> str: + # Custom business logic for email validation + allowed_domains = {'company.com', 'partner.org'} + domain = v.split('@')[1].lower() + if domain not in allowed_domains: + raise ValueError(f'Email domain {domain} not allowed') + return v.lower() +``` + +#### Schema Usage in Tests + +**CRITICAL**: Tests must use real schemas and types from the main project, not redefine their own. + +```python +# ❌ WRONG - Defining schemas in test files +from pydantic import BaseModel + +class ProjectSchema(BaseModel): # Don't do this in tests! + id: str + workspace_id: str + owner_id: str | None + name: str + created_at: datetime + updated_at: datetime + +# ✅ CORRECT - Import schemas from the shared schema package +from your_project.schemas import Project, ProjectSchema +``` + +**Why this matters:** + +- **Type Safety**: Ensures tests use the same types as production code +- **Consistency**: Changes to schemas automatically propagate to tests +- **Maintainability**: Single source of truth for data structures +- **Prevents Drift**: Tests can't accidentally diverge from real schemas + +**Implementation:** + +- All domain schemas should be exported from a shared schema module +- Test files should import schemas from the shared location +- If a schema isn't exported yet, add it to the exports rather than duplicating it +- Mock data factories should use the real Pydantic models + +```python +# ✅ CORRECT - Test factories using real schemas +from your_project.schemas import Project + +def get_mock_project(**overrides: Any) -> Project: + """Factory for creating test Project instances.""" + base_data = { + "id": "proj_123", + "workspace_id": "ws_456", + "owner_id": "user_789", + "name": "Test Project", + "created_at": datetime.now(), + "updated_at": datetime.now(), + } + base_data.update(overrides) + + # Validate against real schema to catch type mismatches + return Project.model_validate(base_data) +``` + +## Code Style + +### Pythonic Programming + +Follow the Zen of Python and modern Python idioms: + +- **Explicit is better than implicit** - use clear names and avoid magic +- **Flat is better than nested** - prefer early returns and guard clauses +- **Simple is better than complex** - don't over-engineer solutions +- **Readability counts** - code is read more often than written +- Use list/dict comprehensions judiciously - prefer clarity over cleverness + +#### Examples of Pythonic Patterns + +```python +from __future__ import annotations + +from decimal import Decimal +from typing import Iterator +from dataclasses import dataclass + +# Good - Pythonic data handling +@dataclass(frozen=True) # Immutable by default +class OrderItem: + price: Decimal + quantity: int + + @property + def total(self) -> Decimal: + return self.price * self.quantity + +@dataclass(frozen=True) +class Order: + items: tuple[OrderItem, ...] # Immutable sequence + shipping_cost: Decimal + + @property + def items_total(self) -> Decimal: + return sum(item.total for item in self.items) + + @property + def total(self) -> Decimal: + return self.items_total + self.shipping_cost + +# Good - Pure function with immutable updates +def apply_discount(order: Order, discount_percent: Decimal) -> Order: + """Apply discount to order items, returning new order.""" + discount_multiplier = (100 - discount_percent) / 100 + + discounted_items = tuple( + OrderItem( + price=item.price * discount_multiplier, + quantity=item.quantity + ) + for item in order.items + ) + + return Order( + items=discounted_items, + shipping_cost=order.shipping_cost + ) + +# Good - Generator for memory efficiency +def process_orders_batch(orders: list[Order]) -> Iterator[ProcessedOrder]: + """Process orders one at a time to avoid memory issues.""" + for order in orders: + validated_order = validate_order(order) + priced_order = apply_promotions(validated_order) + yield finalize_order(priced_order) + +# Good - Context manager for resource management +from contextlib import contextmanager +from typing import Generator + +@contextmanager +def payment_transaction(payment_id: str) -> Generator[PaymentContext, None, None]: + """Manage payment transaction lifecycle.""" + context = PaymentContext(payment_id) + try: + context.begin() + yield context + context.commit() + except Exception: + context.rollback() + raise + finally: + context.close() + +# Usage +def process_payment(payment: Payment) -> ProcessedPayment: + with payment_transaction(payment.id) as txn: + authorized = authorize_payment(payment, txn) + captured = capture_payment(authorized, txn) + return generate_receipt(captured) + +# Good - Using Protocol for duck typing instead of inheritance +from typing import Protocol + +class Payable(Protocol): + """Protocol for objects that can be charged.""" + def charge(self, amount: Decimal) -> PaymentResult: ... + def refund(self, amount: Decimal) -> RefundResult: ... + +class CreditCard: + def charge(self, amount: Decimal) -> PaymentResult: + # Implementation + ... + + def refund(self, amount: Decimal) -> RefundResult: + # Implementation + ... + +class BankAccount: + def charge(self, amount: Decimal) -> PaymentResult: + # Implementation + ... + + def refund(self, amount: Decimal) -> RefundResult: + # Implementation + ... + +def process_payment(payment_method: Payable, amount: Decimal) -> PaymentResult: + """Process payment using any payable method.""" + return payment_method.charge(amount) +``` + +### Code Structure + +- **Use early returns** instead of nested if/else statements +- **Leverage Python's truthiness** but be explicit when dealing with falsy values +- **Keep functions small** and focused on a single responsibility +- **Use dataclasses or Pydantic** for structured data +- **Prefer composition over inheritance** + +```python +# Avoid: Nested conditionals +def process_user_order(user: User, order: Order) -> ProcessedOrder | None: + if user: + if user.is_active: + if user.has_permission('place_order'): + if order: + if order.is_valid(): + # Deep nesting makes code hard to follow + return execute_order(order) + return None + +# Good: Early returns with clear error handling +def process_user_order(user: User, order: Order) -> ProcessedOrder: + if not user: + raise ValueError("User is required") + + if not user.is_active: + raise UserInactiveError("User account is inactive") + + if not user.has_permission('place_order'): + raise PermissionError("User lacks order placement permission") + + if not order: + raise ValueError("Order is required") + + if not order.is_valid(): + raise OrderValidationError("Order failed validation") + + return execute_order(order) + +# Good: Using truthiness appropriately +def get_display_name(user: User) -> str: + """Get user display name with fallback.""" + # Explicit about what we're checking + if not user.first_name and not user.last_name: + return user.email or "Anonymous User" + + name_parts = [user.first_name, user.last_name] + return " ".join(part for part in name_parts if part) + +# Avoid: Checking for specific falsy values when truthiness works +def has_items(order: Order) -> bool: + return len(order.items) > 0 # Unnecessary + +# Good: Using truthiness +def has_items(order: Order) -> bool: + return bool(order.items) +``` + +### Naming Conventions + +- **Functions and variables**: `snake_case` +- **Classes**: `PascalCase` +- **Constants**: `UPPER_SNAKE_CASE` +- **Private attributes**: `_leading_underscore` +- **Modules**: `snake_case.py` +- **Test files**: `test_*.py` or `*_test.py` + +```python +# Good naming examples +class PaymentProcessor: + """Handles payment processing operations.""" + + MAXIMUM_RETRY_ATTEMPTS = 3 + + def __init__(self, api_client: PaymentApiClient) -> None: + self._api_client = api_client + self._retry_count = 0 + + def process_payment(self, payment_request: PaymentRequest) -> PaymentResult: + """Process a payment request with retry logic.""" + return self._attempt_payment_with_retry(payment_request) + + def _attempt_payment_with_retry(self, request: PaymentRequest) -> PaymentResult: + """Internal method for payment processing with retries.""" + # Implementation + ... +``` + +### No Comments in Code + +Code should be self-documenting through clear naming and structure. Comments indicate that the code itself is not clear enough. + +```python +# Avoid: Comments explaining what the code does +def calculate_discount(price: Decimal, customer: Customer) -> Decimal: + # Check if customer is premium + if customer.tier == "premium": + # Apply 20% discount for premium customers + return price * Decimal("0.8") + # Regular customers get 10% discount + return price * Decimal("0.9") + +# Good: Self-documenting code with clear names +PREMIUM_DISCOUNT_MULTIPLIER = Decimal("0.8") +STANDARD_DISCOUNT_MULTIPLIER = Decimal("0.9") + +def is_premium_customer(customer: Customer) -> bool: + return customer.tier == "premium" + +def calculate_discount(price: Decimal, customer: Customer) -> Decimal: + discount_multiplier = ( + PREMIUM_DISCOUNT_MULTIPLIER + if is_premium_customer(customer) + else STANDARD_DISCOUNT_MULTIPLIER + ) + return price * discount_multiplier + +# Avoid: Complex logic with comments +def process_payment(payment: Payment) -> ProcessedPayment: + # First validate the payment + if not validate_payment(payment): + raise PaymentValidationError("Invalid payment") + + # Check if we need to apply 3D secure + if payment.amount > 100 and payment.card.type == "credit": + # Apply 3D secure for credit cards over £100 + secure_payment = apply_3d_secure(payment) + # Process the secure payment + return execute_payment(secure_payment) + + # Process the payment normally + return execute_payment(payment) + +# Good: Extract to well-named functions +SECURE_PAYMENT_THRESHOLD = Decimal("100") + +def requires_3d_secure(payment: Payment) -> bool: + return ( + payment.amount > SECURE_PAYMENT_THRESHOLD + and payment.card.type == "credit" + ) + +def process_payment(payment: Payment) -> ProcessedPayment: + if not validate_payment(payment): + raise PaymentValidationError("Invalid payment") + + secured_payment = ( + apply_3d_secure(payment) + if requires_3d_secure(payment) + else payment + ) + + return execute_payment(secured_payment) +``` + +**Exception**: Docstrings for public APIs are required and should follow Google or NumPy style. Type hints should make the docstring parameter descriptions unnecessary in most cases. + +```python +def calculate_shipping_cost( + items: list[OrderItem], + destination: Address, + shipping_method: ShippingMethod, +) -> Decimal: + """Calculate shipping cost for order items. + + Args: + items: List of items to ship + destination: Shipping destination address + shipping_method: Selected shipping method + + Returns: + Calculated shipping cost + + Raises: + ShippingCalculationError: When shipping cost cannot be determined + """ + # Implementation + ... +``` + +### Keyword Arguments and Default Values + +Use keyword arguments extensively for clarity, especially for functions with multiple parameters: + +```python +# Avoid: Multiple positional parameters +def create_payment( + amount: Decimal, + currency: str, + card_id: str, + customer_id: str, + description: str | None = None, + metadata: dict[str, Any] | None = None, + idempotency_key: str | None = None, +) -> Payment: + # implementation + ... + +# Calling it is unclear +payment = create_payment( + Decimal("100"), + "GBP", + "card_123", + "cust_456", + None, + {"order_id": "order_789"}, + "key_123" +) + +# Good: Use keyword arguments with dataclass or Pydantic model +@dataclass(frozen=True) +class CreatePaymentRequest: + amount: Decimal + currency: str + card_id: str + customer_id: str + description: str | None = None + metadata: dict[str, Any] | None = None + idempotency_key: str | None = None + +def create_payment(request: CreatePaymentRequest) -> Payment: + # implementation using request.amount, request.currency, etc. + ... + +# Clear and readable at call site +payment = create_payment(CreatePaymentRequest( + amount=Decimal("100"), + currency="GBP", + card_id="card_123", + customer_id="cust_456", + metadata={"order_id": "order_789"}, + idempotency_key="key_123", +)) + +# Alternative: Use keyword-only arguments for complex functions +def fetch_customers( + *, # Forces keyword-only arguments + include_inactive: bool = False, + include_pending: bool = False, + include_deleted: bool = False, + sort_by: Literal["date", "name", "value"] = "name", + limit: int = 100, +) -> list[Customer]: + # implementation + ... + +# Self-documenting at call site +customers = fetch_customers( + include_inactive=True, + sort_by="date", + limit=50, +) + +# Good: Using Pydantic for complex configuration +class ProcessOrderConfig(BaseModel): + order: Order + shipping_method: Literal["standard", "express", "overnight"] = "standard" + shipping_address: Address + payment_method: PaymentMethod + save_payment_for_future: bool = False + promotion_codes: list[str] = Field(default_factory=list) + auto_apply_promotions: bool = True + +def process_order(config: ProcessOrderConfig) -> ProcessedOrder: + # Clear access to all configuration + order_with_promotions = ( + apply_available_promotions(config.order) + if config.auto_apply_promotions + else config.order + ) + + return execute_order( + order_with_promotions, + shipping_method=config.shipping_method, + payment_method=config.payment_method, + ) + +# Acceptable: Simple functions with 1-2 parameters +def double(n: int) -> int: + return n * 2 + +def get_user_name(user: User) -> str: + return f"{user.first_name} {user.last_name}" + +# Acceptable: Well-established patterns +numbers = [1, 2, 3] +doubled = [double(n) for n in numbers] +users = fetch_users() +names = [get_user_name(user) for user in users] +``` + +## Development Workflow + +### TDD Process - THE FUNDAMENTAL PRACTICE + +**CRITICAL**: TDD is not optional. Every feature, every bug fix, every change MUST follow this process: + +Follow Red-Green-Refactor strictly: + +1. **Red**: Write a failing test for the desired behavior. NO PRODUCTION CODE until you have a failing test. +2. **Green**: Write the MINIMUM code to make the test pass. Resist the urge to write more than needed. +3. **Refactor**: Assess the code for improvement opportunities. If refactoring would add value, clean up the code while keeping tests green. If the code is already clean and expressive, move on. + +**Common TDD Violations to Avoid:** + +- Writing production code without a failing test first +- Writing multiple tests before making the first one pass +- Writing more production code than needed to pass the current test +- Skipping the refactor assessment step when code could be improved +- Adding functionality "while you're there" without a test driving it + +**Remember**: If you're typing production code and there isn't a failing test demanding that code, you're not doing TDD. + +#### TDD Example Workflow + +```python +# Step 1: Red - Start with the simplest behavior +import pytest +from decimal import Decimal + +def test_order_processing_calculates_total_with_shipping(): + """Should calculate total including shipping cost.""" + order = create_order( + items=[OrderItem(price=Decimal("30"), quantity=1)], + shipping_cost=Decimal("5.99") + ) + + processed = process_order(order) + + assert processed.total == Decimal("35.99") + assert processed.shipping_cost == Decimal("5.99") + +# Step 2: Green - Minimal implementation +@dataclass(frozen=True) +class ProcessedOrder: + items: tuple[OrderItem, ...] + shipping_cost: Decimal + total: Decimal + +def process_order(order: Order) -> ProcessedOrder: + items_total = sum( + item.price * item.quantity + for item in order.items + ) + + return ProcessedOrder( + items=order.items, + shipping_cost=order.shipping_cost, + total=items_total + order.shipping_cost, + ) + +# Step 3: Red - Add test for free shipping behavior +def test_order_processing_applies_free_shipping_over_fifty_pounds(): + """Should apply free shipping for orders over £50.""" + order = create_order( + items=[OrderItem(price=Decimal("60"), quantity=1)], + shipping_cost=Decimal("5.99") + ) + + processed = process_order(order) + + assert processed.shipping_cost == Decimal("0") + assert processed.total == Decimal("60") + +# Step 4: Green - NOW we can add the conditional because both paths are tested +def process_order(order: Order) -> ProcessedOrder: + items_total = sum( + item.price * item.quantity + for item in order.items + ) + + shipping_cost = ( + Decimal("0") + if items_total > Decimal("50") + else order.shipping_cost + ) + + return ProcessedOrder( + items=order.items, + shipping_cost=shipping_cost, + total=items_total + shipping_cost, + ) + +# Step 5: Add edge case tests to ensure 100% behavior coverage +def test_order_processing_charges_shipping_for_exactly_fifty_pounds(): + """Should charge shipping for orders exactly at £50.""" + order = create_order( + items=[OrderItem(price=Decimal("50"), quantity=1)], + shipping_cost=Decimal("5.99") + ) + + processed = process_order(order) + + assert processed.shipping_cost == Decimal("5.99") + assert processed.total == Decimal("55.99") + +# Step 6: Refactor - Extract constants and improve readability +FREE_SHIPPING_THRESHOLD = Decimal("50") + +def calculate_items_total(items: tuple[OrderItem, ...]) -> Decimal: + return sum(item.price * item.quantity for item in items) + +def qualifies_for_free_shipping(items_total: Decimal) -> bool: + return items_total > FREE_SHIPPING_THRESHOLD + +def process_order(order: Order) -> ProcessedOrder: + items_total = calculate_items_total(order.items) + shipping_cost = ( + Decimal("0") + if qualifies_for_free_shipping(items_total) + else order.shipping_cost + ) + + return ProcessedOrder( + items=order.items, + shipping_cost=shipping_cost, + total=items_total + shipping_cost, + ) +``` + +### Refactoring - The Critical Third Step + +Evaluating refactoring opportunities is not optional - it's the third step in the TDD cycle. After achieving a green state and committing your work, you MUST assess whether the code can be improved. However, only refactor if there's clear value - if the code is already clean and expresses intent well, move on to the next test. + +#### What is Refactoring? + +Refactoring means changing the internal structure of code without changing its external behavior. The public API remains unchanged, all tests continue to pass, but the code becomes cleaner, more maintainable, or more efficient. Remember: only refactor when it genuinely improves the code - not all code needs refactoring. + +#### When to Refactor + +- **Always assess after green**: Once tests pass, before moving to the next test, evaluate if refactoring would add value +- **When you see duplication**: But understand what duplication really means (see DRY below) +- **When names could be clearer**: Variable names, function names, or class names that don't clearly express intent +- **When structure could be simpler**: Complex conditional logic, deeply nested code, or long functions +- **When patterns emerge**: After implementing several similar features, useful abstractions may become apparent + +**Remember**: Not all code needs refactoring. If the code is already clean, expressive, and well-structured, commit and move on. Refactoring should improve the code - don't change things just for the sake of change. + +#### Refactoring Guidelines + +##### 1. Commit Before Refactoring + +Always commit your working code before starting any refactoring. This gives you a safe point to return to: + +```bash +git add . +git commit -m "feat: add payment validation" +# Now safe to refactor +``` + +##### 2. Look for Useful Abstractions Based on Semantic Meaning + +Create abstractions only when code shares the same semantic meaning and purpose. Don't abstract based on structural similarity alone - **duplicate code is far cheaper than the wrong abstraction**. + +```python +# Similar structure, DIFFERENT semantic meaning - DO NOT ABSTRACT +def validate_payment_amount(amount: Decimal) -> bool: + return amount > 0 and amount <= Decimal("10000") + +def validate_transfer_amount(amount: Decimal) -> bool: + return amount > 0 and amount <= Decimal("10000") + +# These might have the same structure today, but they represent different +# business concepts that will likely evolve independently. +# Payment limits might change based on fraud rules. +# Transfer limits might change based on account type. +# Abstracting them couples unrelated business rules. + +# Similar structure, SAME semantic meaning - SAFE TO ABSTRACT +def format_user_display_name(first_name: str, last_name: str) -> str: + return f"{first_name} {last_name}".strip() + +def format_customer_display_name(first_name: str, last_name: str) -> str: + return f"{first_name} {last_name}".strip() + +def format_employee_display_name(first_name: str, last_name: str) -> str: + return f"{first_name} {last_name}".strip() + +# These all represent the same concept: "how we format a person's name for display" +# They share semantic meaning, not just structure +def format_person_display_name(first_name: str, last_name: str) -> str: + return f"{first_name} {last_name}".strip() + +# Replace all call sites throughout the codebase and remove original functions +``` + +**Questions to ask before abstracting:** + +- Do these code blocks represent the same concept or different concepts that happen to look similar? +- If the business rules for one change, should the others change too? +- Would a developer reading this abstraction understand why these things are grouped together? +- Am I abstracting based on what the code IS (structure) or what it MEANS (semantics)? + +##### 3. Understanding DRY - It's About Knowledge, Not Code + +DRY (Don't Repeat Yourself) is about not duplicating **knowledge** in the system, not about eliminating all code that looks similar. + +```python +# This is NOT a DRY violation - different knowledge despite similar code +def validate_user_age(age: int) -> bool: + return 18 <= age <= 100 + +def validate_product_rating(rating: int) -> bool: + return 1 <= rating <= 5 + +def validate_years_of_experience(years: int) -> bool: + return 0 <= years <= 50 + +# These functions have similar structure (checking numeric ranges), but they +# represent completely different business rules: +# - User age has legal requirements (18+) and practical limits (100) +# - Product ratings follow a 1-5 star system +# - Years of experience starts at 0 with a reasonable upper bound +# Abstracting them would couple unrelated business concepts and make future +# changes harder. What if ratings change to 1-10? What if legal age changes? + +# This IS a DRY violation - same knowledge in multiple places +FREE_SHIPPING_THRESHOLD = Decimal("50") # Knowledge duplicated! +STANDARD_SHIPPING_COST = Decimal("5.99") # Knowledge duplicated! + +class Order: + def calculate_total(self) -> Decimal: + items_total = sum(item.price for item in self.items) + shipping_cost = ( + Decimal("0") if items_total > Decimal("50") else Decimal("5.99") + ) + return items_total + shipping_cost + +class OrderSummary: + def get_shipping_cost(self, items_total: Decimal) -> Decimal: + return ( + Decimal("0") if items_total > Decimal("50") else Decimal("5.99") + ) + +class ShippingCalculator: + def calculate(self, order_amount: Decimal) -> Decimal: + if order_amount > Decimal("50"): + return Decimal("0") + return Decimal("5.99") + +# Refactored - knowledge in one place +FREE_SHIPPING_THRESHOLD = Decimal("50") +STANDARD_SHIPPING_COST = Decimal("5.99") + +def calculate_shipping_cost(items_total: Decimal) -> Decimal: + return ( + Decimal("0") + if items_total > FREE_SHIPPING_THRESHOLD + else STANDARD_SHIPPING_COST + ) + +# Now all classes use the single source of truth +class Order: + def calculate_total(self) -> Decimal: + items_total = sum(item.price for item in self.items) + return items_total + calculate_shipping_cost(items_total) +``` + +##### 4. Maintain External APIs During Refactoring + +Refactoring must never break existing consumers of your code: + +```python +# Original implementation +def process_payment(payment: Payment) -> ProcessedPayment: + """Process a payment request.""" + # Complex logic all in one function + if payment.amount <= 0: + raise ValueError("Invalid amount") + + if payment.amount > Decimal("10000"): + raise ValueError("Amount too large") + + # ... 50 more lines of validation and processing + + return result + +# Refactored - external API unchanged, internals improved +def process_payment(payment: Payment) -> ProcessedPayment: + """Process a payment request.""" + _validate_payment_amount(payment.amount) + _validate_payment_method(payment.method) + + authorized_payment = _authorize_payment(payment) + captured_payment = _capture_payment(authorized_payment) + + return _generate_receipt(captured_payment) + +# New internal functions - not exported (prefixed with _) +def _validate_payment_amount(amount: Decimal) -> None: + if amount <= 0: + raise ValueError("Invalid amount") + + if amount > Decimal("10000"): + raise ValueError("Amount too large") + +# Tests continue to pass without modification because external API unchanged +``` + +##### 5. Verify and Commit After Refactoring + +**CRITICAL**: After every refactoring: + +1. Run all tests - they must pass without modification +2. Run static analysis (mypy, ruff) - must pass +3. Commit the refactoring separately from feature changes + +```bash +# After refactoring +poetry run pytest # All tests must pass +poetry run mypy . # Type checking must pass +poetry run ruff check . # Linting must pass +poetry run ruff format --check . # Formatting must be correct + +# Only then commit +git add . +git commit -m "refactor: extract payment validation helpers" +``` + +### Commit Guidelines + +- Each commit should represent a complete, working change +- Use conventional commits format: + ``` + feat: add payment validation + fix: correct date formatting in payment processor + refactor: extract payment validation logic + test: add edge cases for payment validation + ``` +- Include test changes with feature changes in the same commit + +### Pull Request Standards + +- Every PR must have all tests passing +- All linting and type checking must pass +- Work in small increments that maintain a working state +- PRs should be focused on a single feature or fix +- Include description of the behavior change, not implementation details + +## Working with Claude + +### Expectations + +When working with my Python code: + +1. **ALWAYS FOLLOW TDD** - No production code without a failing test. This is not negotiable. +2. **Think deeply** before making any edits +3. **Understand the full context** of the code and requirements +4. **Ask clarifying questions** when requirements are ambiguous +5. **Think from first principles** - don't make assumptions +6. **Assess refactoring after every green** - Look for opportunities to improve code structure, but only refactor if it adds value +7. **Keep project docs current** - update them whenever you introduce meaningful changes + +### Code Changes + +When suggesting or making changes: + +- **Start with a failing test** - always. No exceptions. +- After making tests pass, always assess refactoring opportunities (but only refactor if it adds value) +- After refactoring, verify all tests and static analysis pass, then commit +- Respect the existing patterns and conventions +- Maintain test coverage for all behavior changes +- Keep changes small and incremental +- Ensure all type checking requirements are met +- Use proper Python idioms and patterns +- Provide rationale for significant design decisions + +**If you find yourself writing production code without a failing test, STOP immediately and write the test first.** + +### Communication + +- Be explicit about trade-offs in different approaches +- Explain the reasoning behind significant design decisions +- Flag any deviations from these guidelines with justification +- Suggest improvements that align with these principles +- When unsure, ask for clarification rather than assuming + +## Example Patterns + +### Error Handling + +Use Python's exception system effectively: + +```python +# Good - Custom exception hierarchy +class PaymentError(Exception): + """Base exception for payment-related errors.""" + pass + +class PaymentValidationError(PaymentError): + """Raised when payment validation fails.""" + pass + +class InsufficientFundsError(PaymentError): + """Raised when account has insufficient funds.""" + pass + +# Good - Early returns with meaningful exceptions +def process_payment(payment: Payment, account: Account) -> ProcessedPayment: + if not is_valid_payment(payment): + raise PaymentValidationError("Payment validation failed") + + if not has_sufficient_funds(payment, account): + raise InsufficientFundsError("Insufficient funds in account") + + return execute_payment(payment, account) + +# Also good - Result pattern for non-exceptional cases +from typing import Generic, TypeVar +from dataclasses import dataclass + +T = TypeVar('T') +E = TypeVar('E', bound=Exception) + +@dataclass(frozen=True) +class Success(Generic[T]): + value: T + +@dataclass(frozen=True) +class Failure(Generic[E]): + error: E + +Result = Success[T] | Failure[E] + +def process_payment_safe( + payment: Payment, + account: Account +) -> Result[ProcessedPayment, PaymentError]: + if not is_valid_payment(payment): + return Failure(PaymentValidationError("Payment validation failed")) + + if not has_sufficient_funds(payment, account): + return Failure(InsufficientFundsError("Insufficient funds")) + + try: + processed = execute_payment(payment, account) + return Success(processed) + except Exception as e: + return Failure(PaymentError(f"Payment execution failed: {e}")) +``` + +### Testing Behavior + +```python +# Good - tests behavior through public API +def test_payment_processor_declines_insufficient_funds(): + """Should decline payment when account has insufficient funds.""" + payment = get_mock_payment_request(amount=Decimal("1000")) + account = get_mock_account(balance=Decimal("500")) + + with pytest.raises(InsufficientFundsError) as exc_info: + process_payment(payment, account) + + assert "Insufficient funds" in str(exc_info.value) + +def test_payment_processor_processes_valid_payment(): + """Should process payment successfully when all conditions are met.""" + payment = get_mock_payment_request(amount=Decimal("100")) + account = get_mock_account(balance=Decimal("500")) + + result = process_payment(payment, account) + + assert result.status == PaymentStatus.COMPLETED + assert result.remaining_balance == Decimal("400") + +# Good - Parameterized tests for edge cases +@pytest.mark.parametrize("amount,balance,should_succeed", [ + (Decimal("100"), Decimal("500"), True), + (Decimal("500"), Decimal("500"), True), + (Decimal("501"), Decimal("500"), False), + (Decimal("0"), Decimal("500"), False), +]) +def test_payment_processing_with_various_amounts( + amount: Decimal, + balance: Decimal, + should_succeed: bool +): + """Test payment processing with various amount/balance combinations.""" + payment = get_mock_payment_request(amount=amount) + account = get_mock_account(balance=balance) + + if should_succeed: + result = process_payment(payment, account) + assert result.status == PaymentStatus.COMPLETED + else: + with pytest.raises(PaymentError): + process_payment(payment, account) + +# Avoid - testing implementation details +def test_payment_processor_calls_validate_method(): + """This tests implementation, not behavior - AVOID""" + # This would be testing internal method calls + pass +``` + +#### Achieving 100% Coverage Through Business Behavior + +Example showing how validation code gets 100% coverage without testing it directly: + +```python +# payment_validator.py (implementation detail) +def validate_payment_amount(amount: Decimal) -> bool: + """Validate payment amount is within acceptable range.""" + return Decimal("0") < amount <= Decimal("10000") + +def validate_card_details(card: PayingCardDetails) -> bool: + """Validate card details format.""" + return ( + re.match(r'^\d{3,4}$', card.cvv) is not None + and len(card.token) > 0 + ) + +# payment_processor.py (public API) +def process_payment(request: PaymentRequest) -> ProcessedPayment: + """Process a payment request with validation.""" + # Validation is used internally but not exposed + if not validate_payment_amount(request.amount): + raise PaymentValidationError("Invalid payment amount") + + if not validate_card_details(request.paying_card_details): + raise PaymentValidationError("Invalid card details") + + # Process payment... + return execute_payment(request) + +# test_payment_processor.py +class TestPaymentProcessing: + """Tests achieve 100% coverage of validation code without testing validators directly.""" + + def test_rejects_negative_amounts(self): + """Should reject payments with negative amounts.""" + payment = get_mock_payment_request(amount=Decimal("-100")) + + with pytest.raises(PaymentValidationError) as exc_info: + process_payment(payment) + + assert "Invalid payment amount" in str(exc_info.value) + + def test_rejects_zero_amounts(self): + """Should reject payments with zero amounts.""" + payment = get_mock_payment_request(amount=Decimal("0")) + + with pytest.raises(PaymentValidationError) as exc_info: + process_payment(payment) + + assert "Invalid payment amount" in str(exc_info.value) + + def test_rejects_amounts_exceeding_maximum(self): + """Should reject payments exceeding maximum amount.""" + payment = get_mock_payment_request(amount=Decimal("10001")) + + with pytest.raises(PaymentValidationError) as exc_info: + process_payment(payment) + + assert "Invalid payment amount" in str(exc_info.value) + + def test_rejects_invalid_cvv_format(self): + """Should reject payments with invalid CVV format.""" + payment = get_mock_payment_request( + paying_card_details=get_mock_card_details(cvv="12") + ) + + with pytest.raises(PaymentValidationError) as exc_info: + process_payment(payment) + + assert "Invalid card details" in str(exc_info.value) + + def test_rejects_empty_card_token(self): + """Should reject payments with empty card token.""" + payment = get_mock_payment_request( + paying_card_details=get_mock_card_details(token="") + ) + + with pytest.raises(PaymentValidationError) as exc_info: + process_payment(payment) + + assert "Invalid card details" in str(exc_info.value) + + def test_processes_valid_payments_successfully(self): + """Should process valid payments successfully.""" + payment = get_mock_payment_request( + amount=Decimal("100"), + paying_card_details=get_mock_card_details(cvv="123", token="valid-token") + ) + + result = process_payment(payment) + + assert result.status == PaymentStatus.COMPLETED +``` + +### Property-Based Testing with Hypothesis + +```python +from hypothesis import given, strategies as st +from decimal import Decimal + +# Good - Property-based testing for edge cases +@given( + amount=st.decimals( + min_value=Decimal("0.01"), + max_value=Decimal("10000"), + places=2 + ) +) +def test_valid_payment_amounts_are_processed(amount: Decimal): + """Any valid payment amount should be processable.""" + payment = get_mock_payment_request(amount=amount) + + # Should not raise an exception + result = process_payment(payment) + assert result.amount == amount + +@given( + amount=st.one_of( + st.decimals(max_value=Decimal("0")), + st.decimals(min_value=Decimal("10000.01")) + ) +) +def test_invalid_payment_amounts_are_rejected(amount: Decimal): + """Any invalid payment amount should be rejected.""" + payment = get_mock_payment_request(amount=amount) + + with pytest.raises(PaymentValidationError): + process_payment(payment) +``` + +## Common Patterns to Avoid + +### Anti-patterns + +```python +# Avoid: Mutable default arguments +def add_item(items: list[str] = []) -> list[str]: # DANGEROUS! + items.append("new_item") + return items + +# Good: Use None and create new list +def add_item(items: list[str] | None = None) -> list[str]: + if items is None: + items = [] + return [*items, "new_item"] + +# Avoid: Using bare except +try: + process_payment(payment) +except: # Too broad! + handle_error() + +# Good: Catch specific exceptions +try: + process_payment(payment) +except (PaymentValidationError, InsufficientFundsError) as e: + handle_payment_error(e) +except Exception as e: + logger.exception("Unexpected error during payment processing") + raise + +# Avoid: String formatting with % or .format() +name = "John" +message = "Hello, %s!" % name # Old style +message = "Hello, {}!".format(name) # Also old + +# Good: Use f-strings +message = f"Hello, {name}!" + +# Avoid: Manual iteration when comprehensions work +result = [] +for item in items: + if item.is_valid(): + result.append(item.process()) + +# Good: Use comprehensions +result = [item.process() for item in items if item.is_valid()] + +# Avoid: Checking type with isinstance for duck typing +def process_items(items): + if isinstance(items, list): + # Process as list + elif isinstance(items, dict): + # Process as dict + +# Good: Use Protocol or duck typing +from typing import Protocol + +class Processable(Protocol): + def process(self) -> ProcessedResult: ... + +def process_items(items: Processable) -> ProcessedResult: + return items.process() +``` + +## Modern Python Tools + +### Essential Tools Configuration + +```toml +# pyproject.toml +[tool.poetry] +name = "your-project" +version = "0.1.0" +description = "" +authors = ["Your Name "] +readme = "README.md" +packages = [{include = "your_project", from = "src"}] + +[tool.poetry.dependencies] +python = "^3.12" +pydantic = "^2.0.0" +httpx = "^0.24.0" + +[tool.poetry.group.dev.dependencies] +pytest = "^7.0.0" +pytest-mock = "^3.0.0" +hypothesis = "^6.0.0" +mypy = "^1.0.0" +ruff = "^0.1.0" +coverage = {extras = ["toml"], version = "^7.0.0"} + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" + +[tool.mypy] +python_version = "3.12" +strict = true +warn_return_any = true +warn_unused_configs = true +disallow_untyped_defs = true +disallow_incomplete_defs = true + +[tool.ruff] +target-version = "py312" +line-length = 88 + +[tool.ruff.lint] +select = [ + "E", # pycodestyle errors + "W", # pycodestyle warnings + "F", # pyflakes + "I", # isort + "B", # flake8-bugbear + "C4", # flake8-comprehensions + "UP", # pyupgrade +] + +[tool.coverage.run] +source = ["src"] +branch = true + +[tool.coverage.report] +exclude_lines = [ + "pragma: no cover", + "def __repr__", + "raise AssertionError", + "raise NotImplementedError", +] + +[tool.pytest.ini_options] +testpaths = ["tests"] +addopts = "--cov=src --cov-report=html --cov-report=term-missing --cov-fail-under=100" +``` + +### Development Workflow Commands + +```bash +# Install dependencies +poetry install + +# Activate virtual environment +poetry shell + +# Type checking +poetry run mypy . + +# Linting and formatting +poetry run ruff check . +poetry run ruff format . + +# Testing with coverage +poetry run pytest + +# All checks in one command +poetry run mypy . && poetry run ruff check . && poetry run ruff format --check . && poetry run pytest + +# Add new dependencies +poetry add package-name + +# Add development dependencies +poetry add --group dev package-name +``` + +## Resources and References + +- [Python Official Documentation](https://docs.python.org/3/) +- [PEP 8 - Style Guide for Python Code](https://pep8.org/) +- [Pydantic Documentation](https://docs.pydantic.dev/) +- [pytest Documentation](https://docs.pytest.org/) +- [mypy Documentation](https://mypy.readthedocs.io/) +- [Hypothesis Documentation](https://hypothesis.readthedocs.io/) +- [The Zen of Python](https://peps.python.org/pep-0020/) + +## Summary + +The key is to write clean, testable, Pythonic code that evolves through small, safe increments. Every change should be driven by a test that describes the desired behavior, and the implementation should be the simplest thing that makes that test pass. Leverage Python's strengths: readability, expressiveness, and powerful standard library. When in doubt, favor simplicity and clarity over cleverness, and always remember that code is read far more often than it is written. + diff --git a/src/activity-service/Makefile b/src/activity-service/Makefile index 4905a286..e8f94c09 100644 --- a/src/activity-service/Makefile +++ b/src/activity-service/Makefile @@ -1,4 +1,4 @@ -.PHONY: dev lint mypy-lint complex coverage pre-commit sort deploy destroy deps unit infra-tests integration e2e coverage-tests docs lint-docs build format format-fix compare-openapi openapi pr watch update-deps +.PHONY: dev lint mypy-lint complex coverage pre-commit sort deploy destroy deps unit infra-tests integration e2e coverage-tests docs lint-docs build build-terraform terraform-deploy terraform-destroy format format-fix compare-openapi openapi pr watch update-deps PYTHON := ".venv/bin/python3" .ONESHELL: # run all commands in a single shell, ensuring it runs within a local virtual env @@ -45,9 +45,15 @@ unit: poetry run pytest tests/unit --cov-config=.coveragerc --cov=activity_service --cov-report xml build: deps + rm -rf .build mkdir -p .build/lambdas ; cp -r activity_service .build/lambdas mkdir -p .build/common_layer ; poetry export --without=dev --format=requirements.txt > .build/common_layer/requirements.txt +build-terraform: build + @echo "Creating ZIP files for Terraform deployment" + cd .build/lambdas && zip -r ../activity_service.zip . + cd .build/common_layer && pip install --target python/lib/python3.13/site-packages -r requirements.txt && zip -r ../common_layer.zip python + integration-test: poetry run pytest tests/integration --cov-config=.coveragerc --cov=activity_service --cov-report xml @@ -76,3 +82,26 @@ update-deps: pre-commit autoupdate npm i --package-lock-only +sam: build + sam build;sam deploy --stack-name ActivityService-${ENV} --parameter-overrides ParameterKey=DDApiKey,ParameterValue=${DD_API_KEY} ParameterKey=DDSite,ParameterValue=${DD_SITE} ParameterKey=Env,ParameterValue=${ENV} ParameterKey=CommitHash,ParameterValue=${COMMIT_HASH} --no-confirm-changeset --no-fail-on-empty-changeset --capabilities CAPABILITY_NAMED_IAM CAPABILITY_AUTO_EXPAND --resolve-s3 --region ${AWS_REGION} --tags DD_PRESERVE_STACK=true + +sam-destroy: + sam delete --stack-name ActivityService-${ENV} --no-prompts + +tf-apply: build-terraform + cd infra;terraform init -backend-config="key=activity-service/${ENV}/terraform.tfstate" -backend-config "bucket=${TF_STATE_BUCKET_NAME}" -backend-config "region=${AWS_REGION}" -reconfigure;terraform apply -var dd_api_key=${DD_API_KEY} -var dd_site=${DD_SITE} -var env=${ENV} -var app_version=${COMMIT_HASH} -var region=${AWS_REGION} -auto-approve + +tf-apply-local: build-terraform + cd infra && \ + terraform init -backend=false -reconfigure && \ + terraform apply \ + -var dd_api_key=${DD_API_KEY} \ + -var dd_site=${DD_SITE} \ + -var env=${ENV} \ + -var app_version=${COMMIT_HASH} \ + -var region=${AWS_REGION} \ + -auto-approve + +tf-destroy: + cd infra;terraform init -backend-config="key=activity-service/${ENV}/terraform.tfstate" -backend-config "bucket=${TF_STATE_BUCKET_NAME}" -backend-config "region=${AWS_REGION}" -reconfigure;terraform destroy -var dd_api_key=${DD_API_KEY} -var dd_site=${DD_SITE} -var env=${ENV} -var app_version=${COMMIT_HASH} -var region=${AWS_REGION} -auto-approve + diff --git a/src/activity-service/cdk/activity_service/api_construct.py b/src/activity-service/cdk/activity_service/api_construct.py index 02b749e2..94a4db12 100644 --- a/src/activity-service/cdk/activity_service/api_construct.py +++ b/src/activity-service/cdk/activity_service/api_construct.py @@ -112,7 +112,7 @@ def _build_lambda_role(self, db: dynamodb.TableV2, idempotency_table: dynamodb.T return iam.Role( self, constants.SERVICE_ROLE_ARN, - role_name=f"{constants.SERVICE_NAME}-{constants.SERVICE_ROLE}-{self.shared_resources.shared_props.environment}", + role_name=f"CDK-{constants.SERVICE_NAME}-{constants.SERVICE_ROLE}-{self.shared_resources.shared_props.environment}", assumed_by=iam.ServicePrincipal('lambda.amazonaws.com'), inline_policies={ 'dynamic_configuration': iam.PolicyDocument( diff --git a/src/activity-service/dev_requirements.txt b/src/activity-service/dev_requirements.txt index 2820c752..3dcadebb 100644 --- a/src/activity-service/dev_requirements.txt +++ b/src/activity-service/dev_requirements.txt @@ -2,9 +2,9 @@ attrs==25.3.0 ; python_version >= "3.13" and python_full_version < "4.0.0" \ --hash=sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3 \ --hash=sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b -aws-cdk-asset-awscli-v1==2.2.237 ; python_version >= "3.13" and python_version < "4.0" \ - --hash=sha256:642805ba143b35d11d5b5e80ab728db2ec8b894b2837b629ad95601e7e189e4c \ - --hash=sha256:e1dd0086af180c381d3ee81eb963a1f469627763e0507982b6f2d4075446bdf4 +aws-cdk-asset-awscli-v1==2.2.240 ; python_version >= "3.13" and python_version < "4.0" \ + --hash=sha256:73a0787fedcc7e2010779593aa0c66398a4bc8e2291c918b07edc11ffd092612 \ + --hash=sha256:bcfa7124d40b9180697489d6875ed1c34a5dbb4db6eaad68148664c0d56b5af1 aws-cdk-asset-node-proxy-agent-v6==2.1.0 ; python_version >= "3.13" and python_version < "4.0" \ --hash=sha256:1f292c0631f86708ba4ee328b3a2b229f7e46ea1c79fbde567ee9eb119c2b0e2 \ --hash=sha256:24a388b69a44d03bae6dbf864c4e25ba650d4b61c008b4568b94ffbb9a69e40e @@ -14,9 +14,9 @@ aws-cdk-aws-lambda-python-alpha==2.201.0a0 ; python_version >= "3.13" and python aws-cdk-cloud-assembly-schema==44.7.0 ; python_version >= "3.13" and python_version < "4.0" \ --hash=sha256:4b74d45e529861835bb31b7a2ce65d8fb12bbd8a336871154397ea87779d60b9 \ --hash=sha256:93fb209874fabc934dfdc6ca34a0be2e423e01cad676d595e68b76f3ac1fcf0a -aws-cdk-lib==2.201.0 ; python_version >= "3.13" and python_version < "4.0" \ - --hash=sha256:0856569d0ecb81414d08d987950261957d331486cd9daa7a115f2cf38b12c64d \ - --hash=sha256:4dfdb59c5ff0341c48b1c91755e729a61d6508d015d2b9d545a825b9194eb1d2 +aws-cdk-lib==2.202.0 ; python_version >= "3.13" and python_version < "4.0" \ + --hash=sha256:38183380494cef1fca47660536d704b9a2af461399580220939306f0c27f9db1 \ + --hash=sha256:cd01bff16595b8f0740b302c16ff9bcf64bf43fe035332052a0b4b89c5338710 babel==2.17.0 ; python_version >= "3.13" and python_full_version < "4.0.0" \ --hash=sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d \ --hash=sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2 @@ -27,12 +27,12 @@ backrefs==5.8 ; python_version >= "3.13" and python_full_version < "4.0.0" \ --hash=sha256:bbef7169a33811080d67cdf1538c8289f76f0942ff971222a16034da88a73486 \ --hash=sha256:c67f6638a34a5b8730812f5101376f9d41dc38c43f1fdc35cb54700f6ed4465d \ --hash=sha256:e3a63b073867dbefd0536425f43db618578528e3896fb77be7141328642a1585 -boto3==1.38.41 ; python_version >= "3.13" and python_full_version < "4.0.0" \ - --hash=sha256:6119e9f272b9f004f052ca78ce94d3fe10198bc159ae808f75c0e1b9c07518bd \ - --hash=sha256:c6710fc533c8e1f5d1f025c74ffe1222c3659094cd51c076ec50c201a54c8f22 -botocore==1.38.41 ; python_version >= "3.13" and python_full_version < "4.0.0" \ - --hash=sha256:06069a06f1352accb1f6c9505d6e323753627112be80a9d2e057c6d9c9779ffd \ - --hash=sha256:98e3fed636ebb519320c4b2d078db6fa6099b052b4bb9b5c66632a5a7fe72507 +boto3==1.39.0 ; python_version >= "3.13" and python_full_version < "4.0.0" \ + --hash=sha256:52a9f07fb9fa60ec6a2be07cd1586a97d8adae2be750121d4c032349cd113221 \ + --hash=sha256:6257f6f7bb87b66342564eab579ce1f0f63a4c1a6f701492f959e59bd7af68e5 +botocore==1.39.0 ; python_version >= "3.13" and python_full_version < "4.0.0" \ + --hash=sha256:2b8701e529a80241b989d83262a629d0d91fbd7a06ded63ecc1c9d529a383d57 \ + --hash=sha256:d8e72850d3450aeca355b654efb32c8370bf824c1945a61cad2395dc2688581e cattrs==24.1.3 ; python_version >= "3.13" and python_full_version < "4.0.0" \ --hash=sha256:981a6ef05875b5bb0c7fb68885546186d306f10f0f6718fe9b96c226e68821ff \ --hash=sha256:adf957dddd26840f27ffbd060a6c4dd3b2192c5b7c2c0525ef1bd8131d8a83f5 diff --git a/src/activity-service/infra/.terraform.lock.hcl b/src/activity-service/infra/.terraform.lock.hcl new file mode 100644 index 00000000..2550fafe --- /dev/null +++ b/src/activity-service/infra/.terraform.lock.hcl @@ -0,0 +1,25 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "5.91.0" + constraints = "~> 5.61, >= 5.77.0" + hashes = [ + "h1:bZ3AM8Qd1veQoUJqOb7OVp/ElmLg/hkz3bHL2DZZ5Tk=", + "zh:03ee14261b25aee94c735ed6ef7cce47900ab7bdf462335432ca034d0ba74ca2", + "zh:32a3759049c9c2cd041d1257cf16cb90a5ce586e1d0a6fe5f8ebd0ec1ba8e071", + "zh:334db69bc6d8643ec4ea432f0e54e851c2394bbe889cca29ca5029db0e4699e8", + "zh:39957a4a900f100ea8d85845a42164a44c9efea8559a9e74ab4f6a1193e20c3e", + "zh:8831396c764815eb367601a522c51c2e9e8fc38bcaa5f5e83f21de771778e9ba", + "zh:8e71ab68c27f909892a063f845d92faa487297ad9bbc67c77a67194e509781e6", + "zh:944df1084a7ea37a4feea0ee6654fd15891ef4829c5453bc149ffbcc0ab9bad7", + "zh:964391527624f2e66a4eb387ad0a30a1b67a896e9395b6d01353f2572723ea03", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:bb956c660185161e8ce1ed1dbf187c9f549d1779673fe798211dd5b02b98c737", + "zh:c237199ca8cd88f4aab4c673f848c77670b90d98a484fef6bcd31a71ff63d9b9", + "zh:c7522f6072f8ba29f4a6d0f994eda8a381ed2f4a41dbe44c4d989c44852cfe63", + "zh:d412a852ced01433c44f222952b60974f7c297a8a21bef62c9a627b050084134", + "zh:e420266b772041fa89e5868594ed21c8c3090d76b3ec0262054f768a7807f5a7", + "zh:ecfcc7844e9e01123920a4b0e667a4688654e3f22f00890ec80ddd78e7312eda", + ] +} diff --git a/src/activity-service/infra/main.tf b/src/activity-service/infra/main.tf new file mode 100644 index 00000000..660e4dfe --- /dev/null +++ b/src/activity-service/infra/main.tf @@ -0,0 +1,24 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +resource "aws_secretsmanager_secret" "dd_api_key_secret" { + name = "/${var.env}/ActivityService/sls-sample-dd-api-key-secret" + recovery_window_in_days = 0 +} + +resource "aws_secretsmanager_secret_version" "dd_api_key_secret_version" { + secret_id = aws_secretsmanager_secret.dd_api_key_secret.id + secret_string = var.dd_api_key +} + +module "activity" { + source = "./services/activity" + dd_api_key_secret_arn = aws_secretsmanager_secret.dd_api_key_secret.arn + dd_site = var.dd_site + env = var.env + app_version = var.app_version +} diff --git a/src/activity-service/infra/modules/api-gateway-cors-resource/main.tf b/src/activity-service/infra/modules/api-gateway-cors-resource/main.tf new file mode 100644 index 00000000..c60a5ede --- /dev/null +++ b/src/activity-service/infra/modules/api-gateway-cors-resource/main.tf @@ -0,0 +1,56 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +resource "aws_api_gateway_resource" "cors_resource" { + path_part = var.path_part + parent_id = var.parent_resource_id + rest_api_id = var.rest_api_id +} + +resource "aws_api_gateway_method" "options_method" { + rest_api_id = var.rest_api_id + resource_id = aws_api_gateway_resource.cors_resource.id + http_method = "OPTIONS" + authorization = "NONE" +} + +resource "aws_api_gateway_method_response" "options_200" { + rest_api_id = var.rest_api_id + resource_id = "${aws_api_gateway_resource.cors_resource.id}" + http_method = "${aws_api_gateway_method.options_method.http_method}" + status_code = "200" + response_models = { + "application/json" = "Empty" + } + response_parameters = { + "method.response.header.Access-Control-Allow-Headers" = true, + "method.response.header.Access-Control-Allow-Methods" = true, + "method.response.header.Access-Control-Allow-Origin" = true + } + depends_on = [aws_api_gateway_method.options_method] +} + +resource "aws_api_gateway_integration" "options_integration" { + rest_api_id = var.rest_api_id + resource_id = "${aws_api_gateway_resource.cors_resource.id}" + http_method = "${aws_api_gateway_method.options_method.http_method}" + type = "MOCK" + depends_on = [aws_api_gateway_method.options_method] +} + +resource "aws_api_gateway_integration_response" "options_integration_response" { + rest_api_id = var.rest_api_id + resource_id = "${aws_api_gateway_resource.cors_resource.id}" + http_method = "${aws_api_gateway_method.options_method.http_method}" + status_code = "${aws_api_gateway_method_response.options_200.status_code}" + response_parameters = { + "method.response.header.Access-Control-Allow-Headers" = "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'", + "method.response.header.Access-Control-Allow-Methods" = "'GET,OPTIONS,POST,PUT'", + "method.response.header.Access-Control-Allow-Origin" = "'*'" + } + depends_on = [aws_api_gateway_method_response.options_200] +} \ No newline at end of file diff --git a/src/activity-service/infra/modules/api-gateway-cors-resource/output.tf b/src/activity-service/infra/modules/api-gateway-cors-resource/output.tf new file mode 100644 index 00000000..50f14152 --- /dev/null +++ b/src/activity-service/infra/modules/api-gateway-cors-resource/output.tf @@ -0,0 +1,18 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +output "id" { + value = aws_api_gateway_resource.cors_resource.id +} + +output "path_part" { + value = aws_api_gateway_resource.cors_resource.path_part +} + +output "resource" { + value = aws_api_gateway_resource.cors_resource +} \ No newline at end of file diff --git a/src/activity-service/infra/modules/api-gateway-cors-resource/variables.tf b/src/activity-service/infra/modules/api-gateway-cors-resource/variables.tf new file mode 100644 index 00000000..20ae08e8 --- /dev/null +++ b/src/activity-service/infra/modules/api-gateway-cors-resource/variables.tf @@ -0,0 +1,20 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +variable "path_part" { + type = string +} + +variable "parent_resource_id" { + type = string +} + +variable "rest_api_id" { + type = string +} + + diff --git a/src/activity-service/infra/modules/api-gateway-lambda-integration/data.tf b/src/activity-service/infra/modules/api-gateway-lambda-integration/data.tf new file mode 100644 index 00000000..d8b92004 --- /dev/null +++ b/src/activity-service/infra/modules/api-gateway-lambda-integration/data.tf @@ -0,0 +1,2 @@ +data "aws_caller_identity" "current" {} +data "aws_region" "current" {} \ No newline at end of file diff --git a/src/activity-service/infra/modules/api-gateway-lambda-integration/main.tf b/src/activity-service/infra/modules/api-gateway-lambda-integration/main.tf new file mode 100644 index 00000000..571f132e --- /dev/null +++ b/src/activity-service/infra/modules/api-gateway-lambda-integration/main.tf @@ -0,0 +1,30 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +resource "aws_api_gateway_method" "method" { + rest_api_id = var.api_id + resource_id = var.api_resource_id + http_method = var.http_method + authorization = "NONE" +} + +resource "aws_api_gateway_integration" "integration" { + rest_api_id = var.api_id + resource_id = var.api_resource_id + http_method = aws_api_gateway_method.method.http_method + integration_http_method = "POST" + type = "AWS_PROXY" + uri = var.function_arn +} + +resource "aws_lambda_permission" "lambda_permission" { + statement_id = "AllowLambdaExecutionFromAPIGateway_${var.function_name}" + action = "lambda:InvokeFunction" + function_name = var.function_name + principal = "apigateway.amazonaws.com" + source_arn = "arn:aws:execute-api:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:${var.api_id}/*/*" +} diff --git a/src/activity-service/infra/modules/api-gateway-lambda-integration/variables.tf b/src/activity-service/infra/modules/api-gateway-lambda-integration/variables.tf new file mode 100644 index 00000000..92d3e117 --- /dev/null +++ b/src/activity-service/infra/modules/api-gateway-lambda-integration/variables.tf @@ -0,0 +1,46 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +variable "api_id" { + description = "The ID of the HTTP API to attach to." + type = string +} + +variable "api_arn" { + description = "The ARN of the HTTP API to attach to." + type = string +} + +variable "api_resource_id" { + description = "The API Gateway resource." + type = string +} + +variable "api_resource_path" { + description = "The path of the API Gateway resource." + type = string +} + +variable "function_arn" { + description = "The ARN of the Lambda function." + type = string +} + +variable "function_name" { + description = "The name of the Lambda function." + type = string +} + +variable "http_method" { + description = "The HTTP method to use (GET, PUT, POST, DELETE)." + type = string +} + +variable "env" { + description = "The environment to use." + type = string +} \ No newline at end of file diff --git a/src/activity-service/infra/modules/api-gateway/main.tf b/src/activity-service/infra/modules/api-gateway/main.tf new file mode 100644 index 00000000..63f6dfd4 --- /dev/null +++ b/src/activity-service/infra/modules/api-gateway/main.tf @@ -0,0 +1,14 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +resource "aws_api_gateway_rest_api" "rest_api" { + name = "${var.api_name}-${var.env}" + + endpoint_configuration { + types = ["REGIONAL"] + } +} \ No newline at end of file diff --git a/src/activity-service/infra/modules/api-gateway/output.tf b/src/activity-service/infra/modules/api-gateway/output.tf new file mode 100644 index 00000000..93262230 --- /dev/null +++ b/src/activity-service/infra/modules/api-gateway/output.tf @@ -0,0 +1,18 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +output "api_id" { + value = aws_api_gateway_rest_api.rest_api.id +} + +output "api_arn" { + value = aws_api_gateway_rest_api.rest_api.arn +} + +output "root_resource_id" { + value = aws_api_gateway_rest_api.rest_api.root_resource_id +} diff --git a/src/activity-service/infra/modules/api-gateway/variables.tf b/src/activity-service/infra/modules/api-gateway/variables.tf new file mode 100644 index 00000000..e7025df9 --- /dev/null +++ b/src/activity-service/infra/modules/api-gateway/variables.tf @@ -0,0 +1,26 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +variable "api_name" { + description = "The name of the HTTP API to create." + type = string +} + +variable "stage_name" { + description = "The name of the API stage to create." + type = string +} + +variable "stage_auto_deploy" { + description = "Should the API stage auto deploy." + type = bool +} + +variable "env" { + description = "The enviornment to deploy to" + type = string +} \ No newline at end of file diff --git a/src/activity-service/infra/modules/lambda-function/main.tf b/src/activity-service/infra/modules/lambda-function/main.tf new file mode 100644 index 00000000..e25b9f71 --- /dev/null +++ b/src/activity-service/infra/modules/lambda-function/main.tf @@ -0,0 +1,121 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +resource "aws_iam_role" "lambda_function_role" { + name = "tf-node-${var.function_name}-lambda-role-${var.env}" + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "lambda.amazonaws.com" + } + } + ] + }) +} + +// The Datadog extension sends log data to Datadog using the telemetry API, disabling CloudWatch prevents 'double paying' for logs +resource "aws_iam_policy" "function_logging_policy" { + name = "TF-${var.service_name}-${var.function_name}-${var.env}-logging-policy" + policy = jsonencode({ + "Version" : "2012-10-17", + "Statement" : [ + { + Action : [ + "logs:CreateLogStream", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + Effect : "Deny", + Resource : "arn:aws:logs:*:*:*" + } + ] + }) +} + +resource "aws_iam_policy" "dd_api_secret_policy" { + name = "tf-node-${var.function_name}-api-key-secret-policy-${var.env}" + policy = jsonencode({ + "Version" : "2012-10-17", + "Statement" : [ + { + Action : [ + "secretsmanager:GetSecretValue" + ], + Effect : "Allow", + Resource : var.dd_api_key_secret_arn + } + ] + }) +} + + +resource "aws_iam_role_policy_attachment" "function_logging_policy_attachment" { + role = aws_iam_role.lambda_function_role.id + policy_arn = aws_iam_policy.function_logging_policy.arn +} +resource "aws_iam_role_policy_attachment" "secrets_retrieval_policy_attachment" { + role = aws_iam_role.lambda_function_role.id + policy_arn = aws_iam_policy.dd_api_secret_policy.arn +} + +resource "aws_iam_role_policy_attachment" "additional_policy_attachments" { + count = length(var.additional_policy_attachments) + role = aws_iam_role.lambda_function_role.id + policy_arn = var.additional_policy_attachments[count.index] +} + +resource "aws_cloudwatch_log_group" "lambda_log_group" { + name = "/aws/lambda/tf-node-${var.function_name}-${var.env}" + retention_in_days = 7 + lifecycle { + prevent_destroy = false + } +} + + +module "aws_lambda_function" { + source = "DataDog/lambda-datadog/aws" + version = "2.0.0" + + filename = var.zip_file + function_name = "tf-node-${var.function_name}-${var.env}" + role = aws_iam_role.lambda_function_role.arn + handler = var.lambda_handler + runtime = "nodejs22.x" + memory_size = var.memory_size + logging_config_log_group = aws_cloudwatch_log_group.lambda_log_group.name + source_code_hash = filebase64sha256(var.zip_file) + timeout = var.function_timeout + + environment_variables = merge(tomap({ + "TEAM": "loyalty" + "DOMAIN": "loyalty" + "DD_API_KEY_SECRET_ARN" : var.dd_api_key_secret_arn + "DD_EXTENSION_VERSION" : "next" + "DD_CAPTURE_LAMBDA_PAYLOAD" : "true" + "DD_LOGS_INJECTION" : "true" + "DD_ENV" : var.env + "DD_SERVICE" : var.service_name + "DD_SITE" : var.dd_site + "DD_VERSION" : var.app_version + "BUILD_ID" : var.app_version + "DD_DATA_STREAMS_ENABLED" = "true" + "DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED" = "true" + "DEPLOYED_AT" : timestamp() + "ENV" : var.env + "POWERTOOLS_SERVICE_NAME" : var.service_name + "POWERTOOLS_LOG_LEVEL" : "INFO" }), + var.environment_variables + ) + + datadog_extension_layer_version = 80 + datadog_node_layer_version = 125 +} diff --git a/src/activity-service/infra/modules/lambda-function/output.tf b/src/activity-service/infra/modules/lambda-function/output.tf new file mode 100644 index 00000000..22b9cfa1 --- /dev/null +++ b/src/activity-service/infra/modules/lambda-function/output.tf @@ -0,0 +1,29 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +output "function_arn" { + value = module.aws_lambda_function.arn + description = "The arn of the lambda function." +} + +output "function_invoke_arn" { + value = module.aws_lambda_function.invoke_arn + description = "The invoke ARN of the lambda function." +} + +output "function_name" { + value = module.aws_lambda_function.function_name + description = "The name of the lambda function." +} + +output function_role_arn { + value = aws_iam_role.lambda_function_role.arn +} + +output function_role_name { + value = aws_iam_role.lambda_function_role.name +} \ No newline at end of file diff --git a/src/activity-service/infra/modules/lambda-function/variables.tf b/src/activity-service/infra/modules/lambda-function/variables.tf new file mode 100644 index 00000000..6fa28b8f --- /dev/null +++ b/src/activity-service/infra/modules/lambda-function/variables.tf @@ -0,0 +1,66 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +variable "service_name" { + description = "The name of the service" + type = string +} + +variable "env" { + description = "The deployment environment" + type = string +} + +variable "app_version" { + default = "latest" + description = "The version of the deployment" + type = string +} + +variable "zip_file" { + description = "The location of the ZIP file" + type = string +} + +variable "function_name" { + description = "The name of the Lambda function" + type = string +} + +variable "lambda_handler" { + description = "The Lambda handler, defined as classlib::namespace.class::method" + type = string +} + +variable "environment_variables" { + description = "Environment variables to pass to the Lambda function" + type = map(string) +} + +variable "dd_api_key_secret_arn" { + type = string +} + +variable "dd_site" { + default = "The Datadog site to use" + type = string +} + +variable "function_timeout" { + type = number + default = 29 +} + +variable "memory_size" { + type = number + default = 512 +} + +variable "additional_policy_attachments" { + type = list(string) + default = [] +} diff --git a/src/activity-service/infra/modules/python-lambda-function/main.tf b/src/activity-service/infra/modules/python-lambda-function/main.tf new file mode 100644 index 00000000..a5a26d79 --- /dev/null +++ b/src/activity-service/infra/modules/python-lambda-function/main.tf @@ -0,0 +1,134 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +resource "aws_iam_role" "lambda_function_role" { + name = "tf-python-${var.function_name}-lambda-role-${var.env}" + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "lambda.amazonaws.com" + } + } + ] + }) +} + +// Basic execution role for Lambda +resource "aws_iam_policy" "function_basic_execution_policy" { + name = "TF-${var.service_name}-${var.function_name}-${var.env}-basic-execution-policy" + policy = jsonencode({ + "Version" : "2012-10-17", + "Statement" : [ + { + Action : [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ], + Effect : "Allow", + Resource : "arn:aws:logs:*:*:*" + } + ] + }) +} + +resource "aws_iam_policy" "dd_api_secret_policy" { + name = "tf-python-${var.function_name}-api-key-secret-policy-${var.env}" + policy = jsonencode({ + "Version" : "2012-10-17", + "Statement" : [ + { + Action : [ + "secretsmanager:GetSecretValue" + ], + Effect : "Allow", + Resource : var.dd_api_key_secret_arn + } + ] + }) +} + +resource "aws_iam_role_policy_attachment" "function_basic_execution_policy_attachment" { + role = aws_iam_role.lambda_function_role.id + policy_arn = aws_iam_policy.function_basic_execution_policy.arn +} + +resource "aws_iam_role_policy_attachment" "secrets_retrieval_policy_attachment" { + role = aws_iam_role.lambda_function_role.id + policy_arn = aws_iam_policy.dd_api_secret_policy.arn +} + +resource "aws_iam_role_policy_attachment" "additional_policy_attachments" { + count = length(var.additional_policy_attachments) + role = aws_iam_role.lambda_function_role.id + policy_arn = var.additional_policy_attachments[count.index] +} + +resource "aws_cloudwatch_log_group" "lambda_log_group" { + name = "/aws/lambda/tf-python-${var.function_name}-${var.env}" + retention_in_days = 1 + lifecycle { + prevent_destroy = false + } +} + +# Create common layer if layer_zip_file is provided +resource "aws_lambda_layer_version" "common_layer" { + count = var.layer_zip_file != null ? 1 : 0 + filename = var.layer_zip_file + layer_name = "tf-python-${var.service_name}-common-${var.env}" + compatible_runtimes = ["python3.13"] + source_code_hash = var.layer_zip_file != null ? filebase64sha256(var.layer_zip_file) : null + + description = "Common dependencies layer for ${var.service_name}" +} + +# Lambda function using Datadog module +module "aws_lambda_function" { + source = "DataDog/lambda-datadog/aws" + version = "3.1.0" + + filename = var.zip_file + function_name = "tf-python-${var.function_name}-${var.env}" + role = aws_iam_role.lambda_function_role.arn + handler = var.lambda_handler + runtime = "python3.13" + memory_size = var.memory_size + logging_config_log_group = aws_cloudwatch_log_group.lambda_log_group.name + source_code_hash = filebase64sha256(var.zip_file) + timeout = var.function_timeout + layers = var.layer_zip_file != null ? concat([aws_lambda_layer_version.common_layer[0].arn], var.additional_layers) : var.additional_layers + + environment_variables = merge(tomap({ + "TEAM" : "activity" + "DOMAIN" : "activity" + "DD_API_KEY_SECRET_ARN" : var.dd_api_key_secret_arn + "DD_EXTENSION_VERSION" : "next" + "DD_CAPTURE_LAMBDA_PAYLOAD" : "true" + "DD_LOGS_INJECTION" : "true" + "DD_ENV" : var.env + "DD_SERVICE" : var.service_name + "DD_SITE" : var.dd_site + "DD_VERSION" : var.app_version + "BUILD_ID" : var.app_version + "DD_DATA_STREAMS_ENABLED" = "true" + "DD_TRACE_REMOVE_INTEGRATION_SERVICE_NAMES_ENABLED" = "true" + "DEPLOYED_AT" : timestamp() + "ENV" : var.env + "POWERTOOLS_SERVICE_NAME" : var.service_name + "POWERTOOLS_LOG_LEVEL" : "INFO" + }), + var.environment_variables + ) + + datadog_extension_layer_version = 82 + datadog_python_layer_version = 110 +} diff --git a/src/activity-service/infra/modules/python-lambda-function/output.tf b/src/activity-service/infra/modules/python-lambda-function/output.tf new file mode 100644 index 00000000..be09a446 --- /dev/null +++ b/src/activity-service/infra/modules/python-lambda-function/output.tf @@ -0,0 +1,33 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +output "function_arn" { + value = module.aws_lambda_function.arn + description = "The arn of the lambda function." +} + +output "function_invoke_arn" { + value = module.aws_lambda_function.invoke_arn + description = "The invoke ARN of the lambda function." +} + +output "function_name" { + value = module.aws_lambda_function.function_name + description = "The name of the lambda function." +} + +output function_role_arn { + value = aws_iam_role.lambda_function_role.arn +} + +output function_role_name { + value = aws_iam_role.lambda_function_role.name +} + +output "common_layer_arn" { + value = var.layer_zip_file != null ? aws_lambda_layer_version.common_layer[0].arn : null +} \ No newline at end of file diff --git a/src/activity-service/infra/modules/python-lambda-function/variables.tf b/src/activity-service/infra/modules/python-lambda-function/variables.tf new file mode 100644 index 00000000..879a0621 --- /dev/null +++ b/src/activity-service/infra/modules/python-lambda-function/variables.tf @@ -0,0 +1,83 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +variable "service_name" { + type = string + description = "The name of the service" +} + +variable "env" { + type = string + description = "The deployment environment" +} + +variable "app_version" { + type = string + description = "The version of the application being deployed" + default = "latest" +} + +variable "zip_file" { + type = string + description = "The path to the Lambda function zip file" +} + +variable "layer_zip_file" { + type = string + description = "The path to the Lambda layer zip file (optional)" + default = null +} + +variable "function_name" { + type = string + description = "The name of the Lambda function" +} + +variable "lambda_handler" { + type = string + description = "The handler function for the Lambda" +} + +variable "environment_variables" { + type = map(string) + description = "Environment variables for the Lambda function" + default = {} +} + +variable "dd_api_key_secret_arn" { + type = string + description = "The ARN of the Datadog API key secret" +} + +variable "dd_site" { + type = string + description = "The Datadog site to use" +} + +variable "function_timeout" { + type = number + description = "The timeout for the Lambda function in seconds" + default = 29 +} + +variable "memory_size" { + type = number + description = "The memory size for the Lambda function in MB" + default = 512 +} + +variable "additional_policy_attachments" { + type = list(string) + description = "Additional IAM policy ARNs to attach to the Lambda role" + default = [] +} + +variable "additional_layers" { + type = list(string) + description = "Additional Lambda layer ARNs to attach to the function" + default = [] +} \ No newline at end of file diff --git a/src/activity-service/infra/modules/shared_bus_to_domain/main.tf b/src/activity-service/infra/modules/shared_bus_to_domain/main.tf new file mode 100644 index 00000000..bbbaf0d2 --- /dev/null +++ b/src/activity-service/infra/modules/shared_bus_to_domain/main.tf @@ -0,0 +1,105 @@ +data "aws_iam_policy_document" "allow_domain_bus_put_events" { + count = length(var.shared_bus_name) > 0 ? 1 : 0 + statement { + actions = ["events:PutEvents"] + resources = [ + var.domain_bus_arn + ] + } +} + +resource "aws_iam_policy" "shared_eb_publish" { + count = length(var.shared_bus_name) > 0 ? 1 : 0 + name = "${var.rule_name}-publish-${var.env}" + path = "/" + policy = data.aws_iam_policy_document.allow_domain_bus_put_events[count.index].json +} + +resource "aws_iam_role" "shared_eb_publish_role" { + count = length(var.shared_bus_name) > 0 ? 1 : 0 + name = "${var.rule_name}-publish-role-${var.env}" + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "events.amazonaws.com" + } + } + ] + }) +} + +resource "aws_iam_role_policy_attachment" "shared_eb_publish_role_attachment" { + count = length(var.shared_bus_name) > 0 ? 1 : 0 + role = aws_iam_role.shared_eb_publish_role[count.index].id + policy_arn = aws_iam_policy.shared_eb_publish[count.index].arn +} + +// Only deploy rules to the shared bus if the shared bus name is provided +resource "aws_cloudwatch_event_rule" "shared_bus_rule" { + count = length(var.shared_bus_name) > 0 ? 1 : 0 + name = var.rule_name + event_bus_name = var.shared_bus_name + event_pattern = var.event_pattern +} +resource "aws_cloudwatch_event_target" "shared_bus_to_domain_bus_target" { + count = length(var.shared_bus_name) > 0 ? 1 : 0 + rule = aws_cloudwatch_event_rule.shared_bus_rule[count.index].name + arn = var.domain_bus_arn + event_bus_name = var.shared_bus_name + role_arn = aws_iam_role.shared_eb_publish_role[count.index].arn +} + +// Deploy rule to domain bus +resource "aws_cloudwatch_event_rule" "domain_bus_rule" { + name = var.rule_name + event_bus_name = var.domain_bus_name + event_pattern = var.event_pattern +} + +// Configure a Lambda target if the function_name is provided +resource "aws_cloudwatch_event_target" "domain_bus_target" { + count = length(var.function_name) > 0 ? 1 : 0 + rule = aws_cloudwatch_event_rule.domain_bus_rule.name + arn = var.function_arn + event_bus_name = var.domain_bus_name +} +resource "aws_lambda_permission" "allow_db_to_invoke_function" { + count = length(var.function_name) > 0 ? 1 : 0 + action = "lambda:InvokeFunction" + function_name = var.function_name + principal = "events.amazonaws.com" + source_arn = aws_cloudwatch_event_rule.domain_bus_rule.arn +} + +// Configure a SQS target if the queue_name is provided +resource "aws_cloudwatch_event_target" "sqs_target" { + count = length(var.queue_name) > 0 ? 1 : 0 + rule = aws_cloudwatch_event_rule.domain_bus_rule.name + target_id = var.queue_name + arn = var.queue_arn + event_bus_name = var.domain_bus_name +} +data "aws_iam_policy_document" "allow_eb_publish_policy" { + count = length(var.queue_name) > 0 ? 1 : 0 + statement { + sid = "AllowEBPost" + effect = "Allow" + + principals { + type = "Service" + identifiers = ["events.amazonaws.com"] + } + + actions = ["sqs:SendMessage"] + resources = [var.queue_arn] + } +} +resource "aws_sqs_queue_policy" "sqs_target_permissions" { + count = length(var.queue_name) > 0 ? 1 : 0 + queue_url = var.queue_id + policy = data.aws_iam_policy_document.allow_eb_publish_policy[count.index].json +} \ No newline at end of file diff --git a/src/activity-service/infra/modules/shared_bus_to_domain/variables.tf b/src/activity-service/infra/modules/shared_bus_to_domain/variables.tf new file mode 100644 index 00000000..5bf438c2 --- /dev/null +++ b/src/activity-service/infra/modules/shared_bus_to_domain/variables.tf @@ -0,0 +1,60 @@ +variable "env" { + description = "The environment to deploy to" + type = string +} + +variable "rule_name" { + description = "The name of the rule" + type = string +} + +variable "function_name" { + type = string + description = "The name of the function to invoke" + default = "" +} + +variable "function_arn" { + type = string + description = "The Lambda function to invoke" + default = "" +} + +variable "queue_name" { + type = string + description = "The SQS queue name to send messages to" + default = "" +} + +variable "queue_arn" { + type = string + description = "The SQS queue ARN to send messages to" + default = "" +} + +variable "queue_id" { + type = string + description = "The SQS queue URL to send messages to" + default = "" +} + +variable "shared_bus_name" { + description = "The name of the shared event bus" + type = string + default = "" +} + +variable "domain_bus_arn" { + description = "The ARN of the domain bus" + type = string +} + +variable "domain_bus_name" { + description = "The name of the domain bus" + type = string +} + +variable "event_pattern" { + description = "The event to subscribe to" + type = string +} \ No newline at end of file diff --git a/src/activity-service/infra/modules/web-service/data.tf b/src/activity-service/infra/modules/web-service/data.tf new file mode 100644 index 00000000..943d8d58 --- /dev/null +++ b/src/activity-service/infra/modules/web-service/data.tf @@ -0,0 +1,7 @@ +data "aws_secretsmanager_secret" "api_key_secret" { + arn = var.dd_api_key_secret_arn +} + +data "aws_secretsmanager_secret_version" "current_api_key_secret" { + secret_id = data.aws_secretsmanager_secret.api_key_secret.id +} diff --git a/src/activity-service/infra/modules/web-service/main.tf b/src/activity-service/infra/modules/web-service/main.tf new file mode 100644 index 00000000..6c672c8b --- /dev/null +++ b/src/activity-service/infra/modules/web-service/main.tf @@ -0,0 +1,144 @@ +resource "aws_ecs_task_definition" "main" { + family = var.service_name + network_mode = "awsvpc" + requires_compatibilities = ["FARGATE"] + cpu = var.cpu + memory = var.memory_size + execution_role_arn = var.execution_role_arn + task_role_arn = var.task_role_arn + runtime_platform { + operating_system_family = "LINUX" + cpu_architecture = "ARM64" + } + + container_definitions = jsonencode([ + { + name = var.service_name + image = var.image + portMappings = [ + { + containerPort = 3000 + hostPort = 3000 + } + ] + environment = var.environment_variables + secrets = [ + { + name = "SECRET_NAME" + valueFrom = var.dd_api_key_secret_arn + } + ] + logConfiguration = { + logDriver = "awsfirelens" + options = { + Name = "datadog" + Host = "http-intake.logs.datadoghq.eu" + TLS = "on" + dd_service = var.service_name + dd_source = "expressjs", + dd_message_key = "log", + provider = "ecs", + apikey = data.aws_secretsmanager_secret_version.current_api_key_secret.secret_string + } + } + }, + { + name = "DatadogAgent" + image = "public.ecr.aws/datadog/agent:latest" + portMappings = [ + { + containerPort = 8125 + hostPort = 8125 + }, + { + containerPort = 8126 + hostPort = 8126 + } + ] + environment = [ + { + name = "DD_SITE" + value = var.dd_site + }, + { + name = "ECS_FARGATE" + value = "true" + }, + { + name = "DD_LOGS_ENABLED" + value = "false" + }, + { + name = "DD_PROCESS_AGENT_ENABLED" + value = "true" + }, + { + name = "DD_APM_ENABLED" + value = "true" + }, + { + name = "DD_APM_NON_LOCAL_TRAFFIC" + value = "true" + }, + { + name = "DD_DOGSTATSD_NON_LOCAL_TRAFFIC" + value = "false" + }, + { + name = "DD_ECS_TASK_COLLECTION_ENABLED" + value = "true" + }, + { + name = "DD_ENV" + value = var.env + }, + { + name = "DD_SERVICE" + value = var.service_name + }, + { + name = "DD_VERSION" + value = var.app_version + }, + { + name = "DD_APM_IGNORE_RESOURCES" + value = "GET /health" + } + ] + secrets = [ + { + name = "DD_API_KEY" + valueFrom = var.dd_api_key_secret_arn + } + ] + }, + { + name = "log-router" + image = "amazon/aws-for-fluent-bit:latest" + essential = true + firelensConfiguration = { + type = "fluentbit" + options = { + enable-ecs-log-metadata = "true" + } + } + } + ]) +} + +resource "aws_ecs_service" "main" { + name = var.service_name + cluster = var.ecs_cluster_id + task_definition = aws_ecs_task_definition.main.arn + desired_count = 1 + launch_type = "FARGATE" + network_configuration { + subnets = var.subnet_ids + security_groups = var.security_group_ids + } + load_balancer { + target_group_arn = var.target_group_arn + container_name = var.service_name + container_port = 3000 + } +} \ No newline at end of file diff --git a/src/activity-service/infra/modules/web-service/variables.tf b/src/activity-service/infra/modules/web-service/variables.tf new file mode 100644 index 00000000..4d841238 --- /dev/null +++ b/src/activity-service/infra/modules/web-service/variables.tf @@ -0,0 +1,78 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +variable "service_name" { + description = "The name of the service" + type = string +} + +variable "image" { + description = "The full path to the image to use" + type = string +} + +variable "env" { + description = "The deployment environment" + type = string +} + +variable "app_version" { + default = "latest" + description = "The version of the deployment" + type = string +} + +variable "environment_variables" { + description = "Environment variables to pass to the Lambda function" + type = list(object({ + value = string + name = string + })) +} + +variable "dd_api_key_secret_arn" { + type = string +} + +variable "dd_site" { + default = "The Datadog site to use" + type = string +} + +variable "cpu" { + type = string + default = "256" +} + +variable "memory_size" { + type = string + default = "512" +} + +variable "execution_role_arn" { + type = string +} + +variable "task_role_arn" { + type = string +} + +variable "ecs_cluster_id" { + type = string +} + +variable "subnet_ids" { + type = set(string) +} + +variable "security_group_ids" { + type = set(string) +} + +variable "target_group_arn" { + type = string +} diff --git a/src/activity-service/infra/outputs.tf b/src/activity-service/infra/outputs.tf new file mode 100644 index 00000000..0a3dee52 --- /dev/null +++ b/src/activity-service/infra/outputs.tf @@ -0,0 +1,26 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +output "api_endpoint" { + description = "The Activity Service API Gateway endpoint URL" + value = module.activity.api_endpoint +} + +output "activities_table_name" { + description = "The name of the Activities DynamoDB table" + value = module.activity.activities_table_name +} + +output "event_bus_name" { + description = "The name of the Activity Service EventBridge bus" + value = module.activity.event_bus_name +} + +output "activity_queue_url" { + description = "The URL of the Activity SQS queue" + value = module.activity.activity_queue_url +} \ No newline at end of file diff --git a/src/activity-service/infra/providers.tf b/src/activity-service/infra/providers.tf new file mode 100644 index 00000000..0887fab4 --- /dev/null +++ b/src/activity-service/infra/providers.tf @@ -0,0 +1,20 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.61" + } + } + backend "s3" {} +} + +provider "aws" { + region = var.region +} diff --git a/src/activity-service/infra/services/activity/application.tf b/src/activity-service/infra/services/activity/application.tf new file mode 100644 index 00000000..f821c2ae --- /dev/null +++ b/src/activity-service/infra/services/activity/application.tf @@ -0,0 +1,186 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +# SSM parameter for JWT secret access key (non-integrated environments only) +resource "aws_ssm_parameter" "activity_service_access_key" { + count = var.env == "dev" || var.env == "prod" ? 0 : 1 + name = "/${var.env}/ActivityService/secret-access-key" + type = "String" + value = "This is a sample secret key that should not be used in production" + + tags = { + Environment = var.env + Service = "ActivityService" + } +} + +# API Gateway +module "api_gateway" { + source = "../../modules/api-gateway" + api_name = "tf-python-activity-api-${var.env}" + stage_name = var.env + stage_auto_deploy = true + env = var.env +} + +# Activity resource (/api/activity) +module "api_resource" { + source = "../../modules/api-gateway-cors-resource" + path_part = "api" + parent_resource_id = module.api_gateway.root_resource_id + rest_api_id = module.api_gateway.api_id +} + +# Activity resource (/api/activity) +module "activity_resource" { + source = "../../modules/api-gateway-cors-resource" + path_part = "activity" + parent_resource_id = module.api_resource.id + rest_api_id = module.api_gateway.api_id +} + +# Entity type resource (/api/activity/{entity_type}) +module "entity_type_resource" { + source = "../../modules/api-gateway-cors-resource" + path_part = "{entity_type}" + parent_resource_id = module.activity_resource.id + rest_api_id = module.api_gateway.api_id +} + +# Entity ID resource (/api/activity/{entity_type}/{entity_id}) +module "entity_id_resource" { + source = "../../modules/api-gateway-cors-resource" + path_part = "{entity_id}" + parent_resource_id = module.entity_type_resource.id + rest_api_id = module.api_gateway.api_id +} + +# Get Activity Lambda Function +module "get_activity_lambda" { + service_name = "ActivityService" + source = "../../modules/python-lambda-function" + zip_file = "../.build/activity_service.zip" + layer_zip_file = "../.build/common_layer.zip" + function_name = "GetActivity" + lambda_handler = "activity_service.handlers.handle_get_activity.lambda_handler" + dd_api_key_secret_arn = var.dd_api_key_secret_arn + dd_site = var.dd_site + app_version = var.app_version + env = var.env + function_timeout = 29 + memory_size = 512 + environment_variables = { + "TABLE_NAME" : aws_dynamodb_table.activities_table.name + "IDEMPOTENCY_TABLE_NAME" : aws_dynamodb_table.idempotency_table.name + } + additional_policy_attachments = [ + aws_iam_policy.activities_table_read.arn, + aws_iam_policy.idempotency_table_read.arn, + aws_iam_policy.idempotency_table_write.arn, + aws_iam_policy.appconfig_access.arn, + aws_iam_policy.get_jwt_ssm_parameter.arn + ] +} + +# API Gateway integration for Get Activity +module "get_activity_lambda_api" { + source = "../../modules/api-gateway-lambda-integration" + api_id = module.api_gateway.api_id + api_arn = module.api_gateway.api_arn + function_arn = module.get_activity_lambda.function_invoke_arn + function_name = module.get_activity_lambda.function_name + http_method = "GET" + api_resource_id = module.entity_id_resource.id + api_resource_path = module.entity_id_resource.path_part + env = var.env +} + +# Handle Events Lambda Function (SQS processor) +module "handle_events_lambda" { + service_name = "ActivityService" + source = "../../modules/python-lambda-function" + zip_file = "../.build/activity_service.zip" + layer_zip_file = "../.build/common_layer.zip" + function_name = "HandleEvents" + lambda_handler = "activity_service.handlers.create_activity.lambda_handler" + dd_api_key_secret_arn = var.dd_api_key_secret_arn + dd_site = var.dd_site + app_version = var.app_version + env = var.env + function_timeout = 29 + memory_size = 512 + environment_variables = { + "TABLE_NAME" : aws_dynamodb_table.activities_table.name + "IDEMPOTENCY_TABLE_NAME" : aws_dynamodb_table.idempotency_table.name + } + additional_policy_attachments = [ + aws_iam_policy.activities_table_read.arn, + aws_iam_policy.activities_table_write.arn, + aws_iam_policy.idempotency_table_read.arn, + aws_iam_policy.idempotency_table_write.arn, + aws_iam_policy.appconfig_access.arn, + aws_iam_policy.sqs_receive_delete.arn, + aws_iam_policy.eventbridge_publish.arn + ] +} + +# Lambda event source mapping for SQS +resource "aws_lambda_event_source_mapping" "sqs_event_source" { + event_source_arn = aws_sqs_queue.activity_queue.arn + function_name = module.handle_events_lambda.function_arn + batch_size = 10 + function_response_types = ["ReportBatchItemFailures"] + maximum_batching_window_in_seconds = 5 + + depends_on = [ + aws_iam_policy.sqs_receive_delete, + module.handle_events_lambda + ] +} + +# API Gateway deployment +resource "aws_api_gateway_deployment" "rest_api_deployment" { + rest_api_id = module.api_gateway.api_id + depends_on = [ + module.get_activity_lambda_api + ] + triggers = { + redeployment = sha1(jsonencode([ + module.get_activity_lambda_api + ])) + } + variables = { + deployed_at = timestamp() + } + lifecycle { + create_before_destroy = true + } +} + +# API Gateway stage +resource "aws_api_gateway_stage" "rest_api_stage" { + deployment_id = aws_api_gateway_deployment.rest_api_deployment.id + rest_api_id = module.api_gateway.api_id + stage_name = var.env + + tags = { + Environment = var.env + Service = "ActivityService" + } +} + +# SSM parameter for API endpoint +resource "aws_ssm_parameter" "api_endpoint" { + name = "/${var.env}/ActivityService/api-endpoint" + type = "String" + value = aws_api_gateway_stage.rest_api_stage.invoke_url + + tags = { + Environment = var.env + Service = "ActivityService" + } +} \ No newline at end of file diff --git a/src/activity-service/infra/services/activity/database.tf b/src/activity-service/infra/services/activity/database.tf new file mode 100644 index 00000000..e9399014 --- /dev/null +++ b/src/activity-service/infra/services/activity/database.tf @@ -0,0 +1,65 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +# Main activities table +resource "aws_dynamodb_table" "activities_table" { + name = "Activities-${var.env}" + billing_mode = "PAY_PER_REQUEST" + hash_key = "PK" + range_key = "SK" + + attribute { + name = "PK" + type = "S" + } + + attribute { + name = "SK" + type = "S" + } + + point_in_time_recovery { + enabled = true + } + + deletion_protection_enabled = false + + tags = { + Name = "Activities-${var.env}" + Environment = var.env + Service = "ActivityService" + } +} + +# Idempotency table for Lambda Powertools +resource "aws_dynamodb_table" "idempotency_table" { + name = "ActivitiesIdempotency-${var.env}" + billing_mode = "PAY_PER_REQUEST" + hash_key = "id" + + attribute { + name = "id" + type = "S" + } + + ttl { + attribute_name = "expiration" + enabled = true + } + + point_in_time_recovery { + enabled = true + } + + deletion_protection_enabled = false + + tags = { + Name = "ActivitiesIdempotency-${var.env}" + Environment = var.env + Service = "ActivityService" + } +} \ No newline at end of file diff --git a/src/activity-service/infra/services/activity/events.tf b/src/activity-service/infra/services/activity/events.tf new file mode 100644 index 00000000..b614b3d8 --- /dev/null +++ b/src/activity-service/infra/services/activity/events.tf @@ -0,0 +1,214 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +# Activity Service EventBridge bus +resource "aws_cloudwatch_event_bus" "activity_service_bus" { + name = "ActivityService-events-${var.env}" + + tags = { + Name = "ActivityService-events-${var.env}" + Environment = var.env + Service = "ActivityService" + } +} + +# SSM parameters for event bus +resource "aws_ssm_parameter" "event_bus_name" { + name = "/${var.env}/ActivityService/event-bus-name" + type = "String" + value = aws_cloudwatch_event_bus.activity_service_bus.name + + tags = { + Environment = var.env + Service = "ActivityService" + } +} + +resource "aws_ssm_parameter" "event_bus_arn" { + name = "/${var.env}/ActivityService/event-bus-arn" + type = "String" + value = aws_cloudwatch_event_bus.activity_service_bus.arn + + tags = { + Environment = var.env + Service = "ActivityService" + } +} + +# Get shared event bus information for integrated environments +data "aws_ssm_parameter" "shared_eb_name" { + count = var.env == "dev" || var.env == "prod" ? 1 : 0 + name = "/${var.env}/shared/event-bus-name" +} + +data "aws_ssm_parameter" "shared_eb_arn" { + count = var.env == "dev" || var.env == "prod" ? 1 : 0 + name = "/${var.env}/shared/event-bus-arn" +} + +# SQS Dead Letter Queue +resource "aws_sqs_queue" "activity_dead_letter_queue" { + name = "ActivityService-activity-dlq-${var.env}" + message_retention_seconds = 1209600 # 14 days + + tags = { + Name = "ActivityService-activity-dlq-${var.env}" + Environment = var.env + Service = "ActivityService" + } +} + +# Main SQS Queue with DLQ configuration +resource "aws_sqs_queue" "activity_queue" { + name = "ActivityService-activity-queue-${var.env}" + + redrive_policy = jsonencode({ + deadLetterTargetArn = aws_sqs_queue.activity_dead_letter_queue.arn + maxReceiveCount = 3 + }) + + tags = { + Name = "ActivityService-activity-queue-${var.env}" + Environment = var.env + Service = "ActivityService" + } +} + +# SQS Queue Policy to allow EventBridge to send messages +resource "aws_sqs_queue_policy" "activity_queue_policy" { + queue_url = aws_sqs_queue.activity_queue.id + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Principal = { + Service = "events.amazonaws.com" + } + Action = "sqs:SendMessage" + Resource = aws_sqs_queue.activity_queue.arn + } + ] + }) +} + +# Local event variables for reuse +locals { + event_types = [ + "product.productCreated.v1", + "product.productUpdated.v1", + "product.productDeleted.v1", + "users.userCreated.v1", + "orders.orderCreated.v1", + "orders.orderConfirmed.v1", + "orders.orderCompleted.v1", + "inventory.stockUpdated.v1", + "inventory.stockReserved.v1", + "inventory.stockReservationFailed.v1" + ] +} + +# EventBridge rules for local event bus +resource "aws_cloudwatch_event_rule" "activity_local_event_rules" { + for_each = toset(local.event_types) + + name = "activity_${replace(each.value, ".", "_")}-${var.env}" + description = "Activity Service subscription to ${each.value} events" + event_bus_name = aws_cloudwatch_event_bus.activity_service_bus.name + + event_pattern = jsonencode({ + detail-type = [each.value] + }) + + tags = { + Environment = var.env + Service = "ActivityService" + EventType = each.value + } +} + +# Event targets for local rules +resource "aws_cloudwatch_event_target" "activity_local_sqs_targets" { + for_each = toset(local.event_types) + + rule = aws_cloudwatch_event_rule.activity_local_event_rules[each.value].name + event_bus_name = aws_cloudwatch_event_bus.activity_service_bus.name + target_id = "ActivityQueueTarget" + arn = aws_sqs_queue.activity_queue.arn +} + +# IAM role for shared event bus to activity service event bus forwarding +resource "aws_iam_role" "shared_event_bus_to_activity_service_event_bus_role" { + count = var.env == "dev" || var.env == "prod" ? 1 : 0 + name = "SharedEventBusToActivityServiceEventBusRole-${var.env}" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Principal = { + Service = "events.amazonaws.com" + } + Action = "sts:AssumeRole" + } + ] + }) + + inline_policy { + name = "allow-eb-publish" + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = [ + "events:PutEvents" + ] + Resource = [aws_cloudwatch_event_bus.activity_service_bus.arn] + } + ] + }) + } + + tags = { + Environment = var.env + Service = "ActivityService" + } +} + +# EventBridge rules for shared event bus (only for integrated environments) +resource "aws_cloudwatch_event_rule" "activity_shared_event_rules" { + for_each = var.env == "dev" || var.env == "prod" ? toset(local.event_types) : toset([]) + + name = "shared_activity_${replace(each.value, ".", "_")}-${var.env}" + description = "Activity Service subscription to ${each.value} events from shared bus" + event_bus_name = data.aws_ssm_parameter.shared_eb_name[0].value + + event_pattern = jsonencode({ + detail-type = [each.value] + }) + + tags = { + Environment = var.env + Service = "ActivityService" + EventType = each.value + Source = "SharedBus" + } +} + +# Event targets for shared bus rules (forward to activity service bus) +resource "aws_cloudwatch_event_target" "activity_shared_bus_targets" { + for_each = var.env == "dev" || var.env == "prod" ? toset(local.event_types) : toset([]) + + rule = aws_cloudwatch_event_rule.activity_shared_event_rules[each.value].name + event_bus_name = data.aws_ssm_parameter.shared_eb_name[0].value + target_id = "ActivityServiceEventBus" + arn = aws_cloudwatch_event_bus.activity_service_bus.arn + role_arn = aws_iam_role.shared_event_bus_to_activity_service_event_bus_role[0].arn +} \ No newline at end of file diff --git a/src/activity-service/infra/services/activity/iam.tf b/src/activity-service/infra/services/activity/iam.tf new file mode 100644 index 00000000..9f1706e7 --- /dev/null +++ b/src/activity-service/infra/services/activity/iam.tf @@ -0,0 +1,212 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +# DynamoDB read policy for Activities table +resource "aws_iam_policy" "activities_table_read" { + name = "TF-ActivityService-activities-read-${var.env}" + description = "Policy to allow reading from Activities DynamoDB table" + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = [ + "dynamodb:GetItem", + "dynamodb:Query" + ] + Resource = aws_dynamodb_table.activities_table.arn + } + ] + }) + + tags = { + Environment = var.env + Service = "ActivityService" + } +} + +# DynamoDB write policy for Activities table +resource "aws_iam_policy" "activities_table_write" { + name = "TF-ActivityService-activities-write-${var.env}" + description = "Policy to allow writing to Activities DynamoDB table" + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = [ + "dynamodb:PutItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem" + ] + Resource = aws_dynamodb_table.activities_table.arn + } + ] + }) + + tags = { + Environment = var.env + Service = "ActivityService" + } +} + +# DynamoDB read policy for Idempotency table +resource "aws_iam_policy" "idempotency_table_read" { + name = "TF-ActivityService-idempotency-read-${var.env}" + description = "Policy to allow reading from Idempotency DynamoDB table" + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = [ + "dynamodb:GetItem" + ] + Resource = aws_dynamodb_table.idempotency_table.arn + } + ] + }) + + tags = { + Environment = var.env + Service = "ActivityService" + } +} + +# DynamoDB write policy for Idempotency table +resource "aws_iam_policy" "idempotency_table_write" { + name = "TF-ActivityService-idempotency-write-${var.env}" + description = "Policy to allow writing to Idempotency DynamoDB table" + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = [ + "dynamodb:PutItem", + "dynamodb:UpdateItem", + "dynamodb:DeleteItem" + ] + Resource = aws_dynamodb_table.idempotency_table.arn + } + ] + }) + + tags = { + Environment = var.env + Service = "ActivityService" + } +} + +# AppConfig access policy +resource "aws_iam_policy" "appconfig_access" { + name = "TF-ActivityService-appconfig-access-${var.env}" + description = "Policy to allow access to AWS AppConfig" + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = [ + "appconfig:GetLatestConfiguration", + "appconfig:StartConfigurationSession" + ] + Resource = "*" + } + ] + }) + + tags = { + Environment = var.env + Service = "ActivityService" + } +} + +# SSM parameter access policy for JWT secret +resource "aws_iam_policy" "get_jwt_ssm_parameter" { + name = "TF-ActivityService-get-jwt-ssm-parameter-${var.env}" + description = "Policy to allow reading JWT secret from SSM Parameter Store" + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = [ + "ssm:GetParameter" + ] + Resource = var.env == "dev" || var.env == "prod" ? "arn:aws:ssm:*:*:parameter/${var.env}/shared/secret-access-key" : aws_ssm_parameter.activity_service_access_key[0].arn + } + ] + }) + + tags = { + Environment = var.env + Service = "ActivityService" + } +} + +# SQS receive and delete message policy +resource "aws_iam_policy" "sqs_receive_delete" { + name = "TF-ActivityService-sqs-receive-delete-${var.env}" + description = "Policy to allow receiving and deleting messages from SQS" + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = [ + "sqs:ReceiveMessage", + "sqs:DeleteMessage", + "sqs:GetQueueAttributes" + ] + Resource = [ + aws_sqs_queue.activity_queue.arn, + aws_sqs_queue.activity_dead_letter_queue.arn + ] + } + ] + }) + + tags = { + Environment = var.env + Service = "ActivityService" + } +} + +# EventBridge publish policy +resource "aws_iam_policy" "eventbridge_publish" { + name = "TF-ActivityService-eventbridge-publish-${var.env}" + description = "Policy to allow publishing events to EventBridge" + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = [ + "events:PutEvents" + ] + Resource = [ + aws_cloudwatch_event_bus.activity_service_bus.arn, + var.env == "dev" || var.env == "prod" ? data.aws_ssm_parameter.shared_eb_arn[0].value : aws_cloudwatch_event_bus.activity_service_bus.arn + ] + } + ] + }) + + tags = { + Environment = var.env + Service = "ActivityService" + } +} \ No newline at end of file diff --git a/src/activity-service/infra/services/activity/outputs.tf b/src/activity-service/infra/services/activity/outputs.tf new file mode 100644 index 00000000..15b5837d --- /dev/null +++ b/src/activity-service/infra/services/activity/outputs.tf @@ -0,0 +1,66 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +output "api_endpoint" { + description = "The API Gateway endpoint URL" + value = aws_api_gateway_stage.rest_api_stage.invoke_url +} + +output "activities_table_name" { + description = "The name of the Activities DynamoDB table" + value = aws_dynamodb_table.activities_table.name +} + +output "activities_table_arn" { + description = "The ARN of the Activities DynamoDB table" + value = aws_dynamodb_table.activities_table.arn +} + +output "idempotency_table_name" { + description = "The name of the Idempotency DynamoDB table" + value = aws_dynamodb_table.idempotency_table.name +} + +output "idempotency_table_arn" { + description = "The ARN of the Idempotency DynamoDB table" + value = aws_dynamodb_table.idempotency_table.arn +} + +output "event_bus_name" { + description = "The name of the Activity Service EventBridge bus" + value = aws_cloudwatch_event_bus.activity_service_bus.name +} + +output "event_bus_arn" { + description = "The ARN of the Activity Service EventBridge bus" + value = aws_cloudwatch_event_bus.activity_service_bus.arn +} + +output "activity_queue_url" { + description = "The URL of the Activity SQS queue" + value = aws_sqs_queue.activity_queue.url +} + +output "activity_queue_arn" { + description = "The ARN of the Activity SQS queue" + value = aws_sqs_queue.activity_queue.arn +} + +output "get_activity_function_arn" { + description = "The ARN of the Get Activity Lambda function" + value = module.get_activity_lambda.function_arn +} + +output "handle_events_function_arn" { + description = "The ARN of the Handle Events Lambda function" + value = module.handle_events_lambda.function_arn +} + +output "common_layer_arn" { + description = "The ARN of the common Lambda layer" + value = module.get_activity_lambda.common_layer_arn +} \ No newline at end of file diff --git a/src/activity-service/infra/services/activity/variables.tf b/src/activity-service/infra/services/activity/variables.tf new file mode 100644 index 00000000..e19fee10 --- /dev/null +++ b/src/activity-service/infra/services/activity/variables.tf @@ -0,0 +1,28 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +variable "dd_api_key_secret_arn" { + type = string + description = "The ARN of the Datadog API key secret" +} + +variable "dd_site" { + type = string + description = "The Datadog site to use" + default = "datadoghq.com" +} + +variable "env" { + type = string + description = "The deployment environment" +} + +variable "app_version" { + type = string + description = "The version of the application being deployed" + default = "latest" +} \ No newline at end of file diff --git a/src/activity-service/infra/variables.tf b/src/activity-service/infra/variables.tf new file mode 100644 index 00000000..775050c2 --- /dev/null +++ b/src/activity-service/infra/variables.tf @@ -0,0 +1,38 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2024 Datadog, Inc. +// + +variable "dd_api_key" { + type = string + description = "The Datadog API key" +} + +variable "dd_site" { + type = string + description = "The Datadog site to use" + default = "datadoghq.com" +} + +variable "env" { + type = string + description = "The deployment environment" +} + +variable "app_version" { + type = string + description = "The version of the application being deployed" + default = "latest" +} + +variable "region" { + type = string + description = "The AWS region to deploy to" +} + +variable "tf_state_bucket_name" { + type = string + default = "The name of the S3 bucket to store state" +} diff --git a/src/activity-service/lambda_requirements.txt b/src/activity-service/lambda_requirements.txt index 44656f82..57ce0514 100644 --- a/src/activity-service/lambda_requirements.txt +++ b/src/activity-service/lambda_requirements.txt @@ -10,80 +10,80 @@ aws-lambda-powertools==3.15.1 ; python_version >= "3.13" and python_full_version aws-xray-sdk==2.14.0 ; python_version >= "3.13" and python_full_version < "4.0.0" \ --hash=sha256:aab843c331af9ab9ba5cefb3a303832a19db186140894a523edafc024cc0493c \ --hash=sha256:cfbe6feea3d26613a2a869d14c9246a844285c97087ad8f296f901633554ad94 -boto3==1.38.41 ; python_version >= "3.13" and python_full_version < "4.0.0" \ - --hash=sha256:6119e9f272b9f004f052ca78ce94d3fe10198bc159ae808f75c0e1b9c07518bd \ - --hash=sha256:c6710fc533c8e1f5d1f025c74ffe1222c3659094cd51c076ec50c201a54c8f22 -botocore==1.38.41 ; python_version >= "3.13" and python_full_version < "4.0.0" \ - --hash=sha256:06069a06f1352accb1f6c9505d6e323753627112be80a9d2e057c6d9c9779ffd \ - --hash=sha256:98e3fed636ebb519320c4b2d078db6fa6099b052b4bb9b5c66632a5a7fe72507 +boto3==1.39.0 ; python_version >= "3.13" and python_full_version < "4.0.0" \ + --hash=sha256:52a9f07fb9fa60ec6a2be07cd1586a97d8adae2be750121d4c032349cd113221 \ + --hash=sha256:6257f6f7bb87b66342564eab579ce1f0f63a4c1a6f701492f959e59bd7af68e5 +botocore==1.39.0 ; python_version >= "3.13" and python_full_version < "4.0.0" \ + --hash=sha256:2b8701e529a80241b989d83262a629d0d91fbd7a06ded63ecc1c9d529a383d57 \ + --hash=sha256:d8e72850d3450aeca355b654efb32c8370bf824c1945a61cad2395dc2688581e bytecode==0.16.2 ; python_version >= "3.13" and python_full_version < "4.0.0" \ --hash=sha256:0a7dea0387ec5cae5ec77578690c5ca7470c8a202c50ce64a426d86380cddd7f \ --hash=sha256:f05020b6dc1f48cdadd946f7c3a03131ba0f312bd103767c5d75559de5c308f8 cachetools==6.1.0 ; python_version >= "3.13" and python_full_version < "4.0.0" \ --hash=sha256:1c7bb3cf9193deaf3508b7c5f2a79986c13ea38965c5adcff1f84519cf39163e \ --hash=sha256:b4c4f404392848db3ce7aac34950d17be4d864da4b8b66911008e430bc544587 -ddtrace==3.9.3 ; python_version >= "3.13" and python_full_version < "4.0.0" \ - --hash=sha256:068d4cfbffa2d6bd19acb8fa2db74718310bf44a1d12f2d63b005d1e0fd93709 \ - --hash=sha256:08b3a16ab2ad95aa65f16e1563769b6af22d3c3083c994c2761e1a7f22d28915 \ - --hash=sha256:09a0c7d6b13b361526b6306beabc0e8e397e22ca03125701071b3bdda80ebb4f \ - --hash=sha256:1137c3249bca6a29d40a916d85cc52171824c362d8eeef9440e72955e5d30d4e \ - --hash=sha256:137f84cbf599ace230d4d842e520910a6dd9c2a19022c80c8b55583da070fbac \ - --hash=sha256:19452e4024bb9b5e768d0fedfe461a9639a2f2a2077b31a2e0bd7128529bbb4c \ - --hash=sha256:1b46233464b7537fe1842b7b8d1cb9a9dc572f2a767386100df1baa5017924bd \ - --hash=sha256:2384d6c30b582c1402b43b0ace1162c40e82fcfa7d438783b8ee32c26ec135a1 \ - --hash=sha256:2533d4f05d4f4c0d1726c7926aecc2e97154954164c0a1e4c37d3b7660555203 \ - --hash=sha256:28f6623d13c13bdca3379862b53b11401d9056cd8af4b47881c3927b0c8ea2a0 \ - --hash=sha256:2d71f08970efce1cd8a3ecfc95a74d3b15da6c8870a5347693c100f64fc06984 \ - --hash=sha256:30f5fbcd0940b35072c6d7fbfef810a362a3d580e9f2001dd1eb3f39527f7f83 \ - --hash=sha256:32219984d5c30fdc44a802b4cb9bab459e50361ea42cbca72d6d33c7041aef26 \ - --hash=sha256:42da87d7b78967b8f5e8adbe58edafd4e90b0431c6e37616c5faa4343ce5e77b \ - --hash=sha256:45b869826d91f3642bad362a7a4fd8450090bac14a70f3dedb9c804090cab541 \ - --hash=sha256:45bca3420798d345e1702b73fbce45f38f148c64374d3e2d18b7b115248a8ae9 \ - --hash=sha256:4c67d47b3833b957e7458bd21aafac174faaabada388bce80d7d054503963143 \ - --hash=sha256:4cc6db6723e59bc8fb229ab177f3467dfe98aba650c5949d93fd18349f4d915a \ - --hash=sha256:55d7b42d20e644cd819faf3fa41fc63ff6cbf85ce337d12d5e609a896c2b2e8e \ - --hash=sha256:5d8171be0bf47928037a5844bb0ca7820935b465d7bcec9fe022455f00b0f690 \ - --hash=sha256:60cc27d37abad390bd1e1c408368d30fd6348431bf2b8272e2ce77b521d4ece8 \ - --hash=sha256:662c2b3e1e5e2f6a56513e2bc8d370c60a8de532ba9a01e2159fee283bcd1784 \ - --hash=sha256:695f76f481c7ed5794cfd266becdddd806304f410e5b698e9006b810687b8975 \ - --hash=sha256:6e06f8379ef3c7d9d8234a1cbeb55c5af4ab763ddf4268381b5db67eb05fe397 \ - --hash=sha256:77c2af25dbb375f3780acf34fb5ba3253b756669400ecbf5f13db2a555094bd2 \ - --hash=sha256:78e1ba4602328ccfee08f18c020c151a63c1882baf358dfecda32929f91f56ca \ - --hash=sha256:842549c8f83befa8066423b696c026029168ab50fd27a11e24d4ef727b776174 \ - --hash=sha256:85888bfbd03ea0ec95d2cb6c35a5ffb5c00031ad813ef7e026d39a481b5f8f63 \ - --hash=sha256:8e83909c4961b60221ec1bd9f8ba98bec0c9e4717c47faf4fad9d60e4f0a1b96 \ - --hash=sha256:8edce9f0284931a4e976ec7cf16b260cdb57e209bcc0d258ba3fca568b8e73db \ - --hash=sha256:936ab058a43ab4ecf03d41e6199aeb0f76c82333eeef9ff5fae90106a7d71ab2 \ - --hash=sha256:97090dd988326a48403d4cc2aa11052de15d447e57a83c2335cd56e1c7560f04 \ - --hash=sha256:9b57a4a2ed7043aba1d859d7277b64d61dfc0687b431e081453e02186484ecf3 \ - --hash=sha256:9be2aff339f0ccca2f9d9fde19f1dd8117de6bd307a59ebd67198248bf3a2f41 \ - --hash=sha256:9ce3d9435218feada6f2d0e2cffa34e0ea7e376f6dd9f37011d199448ebc4e90 \ - --hash=sha256:9d0d2d41ea05e1e60a3adff07670ac5e78c51d2c28c4b861cf6415a75da2f8e4 \ - --hash=sha256:9d5ef534db804ab4f84ef1fa30ad6144695eefadf7a0263f14b69418a4a5f2b6 \ - --hash=sha256:9f2e5dd193b701651fe735cc02da5b3223b2ae9e4f6a028b10da47e6ba8600b1 \ - --hash=sha256:a29d358a5c5e382df25c06420acaf3ea4b4214e607da946de47f83f060e3e2e0 \ - --hash=sha256:a3344c4ebb3da8660df5aba758442d620100fad0e7d98b6702f4b06f1f3daba8 \ - --hash=sha256:a413ac19aba8c50bbe3a671dcc9886c5d30ae0514257ea05494235c35368c21f \ - --hash=sha256:ab9312b0d417f297ef38305631ab85e75b20ec44b5fcf044b5b4cae28e24af2d \ - --hash=sha256:acd5ce9aa7131e46ebffb085c3cdf4847b3d7ae9ab8ba193f779188f3fccb001 \ - --hash=sha256:b2553355df4c8bac52041b2f08e1b692b03fe1068f9686fb400ae188356c303c \ - --hash=sha256:b2c831a48e9ce4f9f1e40c9d5d7785710d8192aafdc51fd55f76919370382aea \ - --hash=sha256:b6ee77918b1d50170632c9dfd83167f91682882c24fe3be787c150eecf9c78ec \ - --hash=sha256:b74b71588e004d6884474870252d409da9867fb7ce678e13f97f4ea36eb63444 \ - --hash=sha256:b9fcc0404fdd2a25bb035562e89c9bd27e7fe792ca3d50c0a66b5b946c8f113d \ - --hash=sha256:d1a72898030cb323c496d0c7c69ce4cbcc5ae79c89d46ba8e707e9e3c442b6c3 \ - --hash=sha256:d1a73cd4d69546a0468feea7835e1c5dfe8efab2b237fd07e9c1749446630d3e \ - --hash=sha256:dc7504626bf9b881fe04413020b9d199ea66a6e9ea6b0210b6b9af5b9407749f \ - --hash=sha256:df8bca8d76c261f4c2fc0ea1cf30f537502fbd138c78609b94cd55243dabb57b \ - --hash=sha256:e0df3c294e0dfd222c3f040ddcade54e3f3d873fd42a2cc93b420dfa16bb252f \ - --hash=sha256:e1fb98f0e0899594d41867d1167a064eb5e9ec47cf607bdbc29eb9b59f4cd87f \ - --hash=sha256:e3b227460c10fc8ec2f4c5548a0274a7750283b4402786c19c29d39f692ec6ff \ - --hash=sha256:ee54a29c53e2cbf8d07f57798f185280409415a249a968e904c887a12bbcf45e \ - --hash=sha256:f075699a62a2db1356a22382fa667916a15857e9a12b249c4a5bc1c94e4c403f \ - --hash=sha256:f559e8462c2be3e1fdd3abd8e4b041747e709e139d1a34359e6ca3a9aabd12ea \ - --hash=sha256:f8aed9f3f4d7db0e8d4e5d3586a4d64535dc2a33861534aaf7b855377c3f959a \ - --hash=sha256:fd88fbf82405c18acdfcf3dde28032caae16ae8c4fe3f52558866e6bf0533b7b \ - --hash=sha256:fec2d68b718d0f00f164b5ef4c803b89f7e1d0073c27f6e785c0de424db90e79 +ddtrace==3.9.4 ; python_version >= "3.13" and python_full_version < "4.0.0" \ + --hash=sha256:01abb4066b2ffd8125fe024571f20037653e472bbefafef3809d7a7e898ad8ee \ + --hash=sha256:0689955ddab33f8d9adb87114b97d64eed05b8017a288e1c6651b06f72406226 \ + --hash=sha256:09805165f5680b7257ccb5f3f7da6407c14327250f9a318c8029d03a21271c93 \ + --hash=sha256:15127303354075dc8bffe1118243041522032416b5c0f71ed5dac8f934f955d5 \ + --hash=sha256:16671001252cf7bb7f95d0526dc53a28b3ec878ff2b8e41ddce94e6c39acf557 \ + --hash=sha256:1d07be09e53fdcd71f2c30ac3cc3ace9f6bbad5c8185728dee7292857935531c \ + --hash=sha256:1d1bbeda4c7a7f77fc5f3cf7d95e11edd5c441db47bfd3554f128c8482a1d7ab \ + --hash=sha256:1ee655550a4442e58028527b47677c45bbddf7ed70a31b1991a0574d85446c17 \ + --hash=sha256:20f255dd34dcf32939b7f54200014832b8875329ec9216b41ab9ecd481301dae \ + --hash=sha256:2567cf92ee176b94c36812a0468a168c28bcb13f2ad737b39313e1ca4902db12 \ + --hash=sha256:28fd5c7aaf30d7b88a5ef43f4a80f7a54dceee137a76bda1d9c058f23296ab02 \ + --hash=sha256:2c8f9a9d542ce5566505dd84d212e636607bcd7ab40aa5bf512ac7b29d25230c \ + --hash=sha256:2d5c9e2e1cd12312776809adf0a8d04b8c52de3a84e74dcacc882d8875519469 \ + --hash=sha256:325cd3a240845e45d6288f6af252028a418419a11e64af4d716450aee6746830 \ + --hash=sha256:370ab3c5b1590402802ac344b1d192fad815006e7c379d5effc4aec3289ad502 \ + --hash=sha256:397c9c85932e5d9a7d5792faa4311d2db54ef33ed65cfa7019a14567c8708105 \ + --hash=sha256:39e937b9b91a502fc9cf7c124ee5dcb914566a2421b521561b71d3790045a101 \ + --hash=sha256:3df90869f0912778a24e785778b09dbd8a01d51f86ebe49632766f38567f3adf \ + --hash=sha256:5251d3c3c60ef834b53c838714ac38b41dec30e0dbe042eddd2f06c8f5b356d2 \ + --hash=sha256:62f6b2e0b7ad230a3336b328e9efb5eeb7fbb4838b1aa1374a33d82f5a6cec5e \ + --hash=sha256:6343a214231bc4413304e4eaf5cdb23c20eab5945d2ca2789c1e37b9dd814f13 \ + --hash=sha256:6576d121cdf07d24e067f79511e3890595811a635d2ac643eefd0cbdcf3ec5f1 \ + --hash=sha256:68c15a73567e699c8c1441fa2cc964ceddc9379ee0efe5d2d2342d7456f6cf66 \ + --hash=sha256:6d72f980e14f46474bef30f9526b17a733acc1f1dd6fa97a869ed1ec9a0bce42 \ + --hash=sha256:720c3802ddd80d2a4b441d1ed7b0a7c40ab7facd8f92dd7675e83533b2aa7759 \ + --hash=sha256:728f0110341353bb1cb425ab93877c2ca2ddab2f096f0ec1e50c8e26c41c7364 \ + --hash=sha256:73c1614cbc3b77b72e049729e22cec752c8ac80142ad13cd80755d565763f747 \ + --hash=sha256:73d517e8852b947e4fba727e620cc6d549dd19b4f2bc3fefb37fc1773c31b37c \ + --hash=sha256:787d5c6354e01e2374df8c1c0d41cad8abdb3b265ee27f640396e9a932d0adb2 \ + --hash=sha256:7fa77642065489bc619f5af750e483076955accbb8d230f477e5f647fe203d81 \ + --hash=sha256:82773444cd8d268026a64905b3db7a32bfed03b534051d8244d111ad301f0345 \ + --hash=sha256:8601eb960fab75b7cafc1f976097e244c132868de116b31de50209d2818ae796 \ + --hash=sha256:8db657d82ed2a18de07914f27a4bacd90256fb613436506be980359de1c60ceb \ + --hash=sha256:8e70de00f2e4d4d5fc5c25430c58f5c2e7a2169dc5995a61338e07d540dcea9e \ + --hash=sha256:918e9f538d6ff715fe63e65889aa9d4b7cfdf7c091492ba0ff7e8b2734751975 \ + --hash=sha256:944c057f572e2c7a36e71b31a8d1d87306e200001b1fae36319699552a9546bc \ + --hash=sha256:9923b0e488b5d7990618ea10034d81148b53aaec10dc567c962927d08ee877c5 \ + --hash=sha256:9bb80ba47552d52f82da947d9dcbbfeb6c3ef24c4932f045d9c1bc58c15fe49e \ + --hash=sha256:a8733a4e1a500a740792441fb288e39fa5a4aede7362d0d5dad6e1051d20da84 \ + --hash=sha256:afa927dba6e214c7ddf52205ca5f476712ea05a69408a3a68adb11a174aedd1c \ + --hash=sha256:b1a9ee8ecee85a1e695641aa0267f98c6e9e0a9cb45d86a4b0cd15ae73eca342 \ + --hash=sha256:b2b872f7bfb0a17ecef8fa207478055f1b27d2f5c2b9455e9ee20316ed944e32 \ + --hash=sha256:b7c9b012cd6f13cfc62eda62cf2af2e14696cd33212434f8a2cb6c0e09bc9a4c \ + --hash=sha256:bb2472167e47826145be93606335dbf8c49138dba50ea4cc881ad52c834fc0d3 \ + --hash=sha256:bb80929280c6a847e4282259fec9f0357e446844eec9ef3ae4db88aebb284837 \ + --hash=sha256:bb986454b7a066d1d25095b473a08e44dc2d37d37648a13784ad8e0a56f6b301 \ + --hash=sha256:c2c4891fb42a8bb23ef2a787dc14c00047d0f46536eb0eb116a14a4fce12c919 \ + --hash=sha256:c778db5e067c72e186e693739a0bf3ce30258d44393959695e65d25fe442a586 \ + --hash=sha256:cc81653a37755a2034d55c0b88847b8533a1cfdc2e8ac0e5b779ec15acd43f7f \ + --hash=sha256:cdd1fcf023d12cb3bccb738428434a56d73e8bdc536de131ff3f361bd0843a5c \ + --hash=sha256:d635f13e143d338befd6655490ca634dc7df1f647cec6f6240e7ffc045afb4ca \ + --hash=sha256:d9268c5728847383c1ef060848ae8bd6caf570d67fee071ebc21b1d1daa18f36 \ + --hash=sha256:de6db7d26ff7327a44df39ddc79f5caacdee882dea5f2dce2821af85afdbf245 \ + --hash=sha256:e1a0bc433c52e396452dbf251710d812713649c135d856c98e2e23955237e68b \ + --hash=sha256:e4c29497889588a68b508469f1c307b9506665481ac16c782b4510e47cb611d3 \ + --hash=sha256:ef24eb6750b7004492e0ce4aacbbd4969aad11a3a6eb164d2e3c2ce9a6bf3829 \ + --hash=sha256:f50321e6dcbea49cfd5e1b6c857cc0dc16408044f02e1e48f88c73a3ea1a6933 \ + --hash=sha256:f59b3623fc792f4b820db740ba77e51c2169d9bbcc9d04894a1b698aa5ce0147 \ + --hash=sha256:f63e7a4ca88251304e8a6a757daa944a86b1104602176196eb73bd0da3ac5701 \ + --hash=sha256:f7258bd2e9532daf55059ec077395db1ab284493a8a2d6001fad247c5f8a57f2 \ + --hash=sha256:fda91bc31cc0184d651c04637620903d4d4cad224ff189686034495bf052e96d dnspython==2.7.0 ; python_version >= "3.13" and python_full_version < "4.0.0" \ --hash=sha256:b4c34b7d10b51bcc3a5071e7b8dee77939f1e878477eeecc965e9835f63c6c86 \ --hash=sha256:ce9c432eda0dc91cf618a5cedf1a4e142651196bbcd2c80e89ed5a907e5cfaf1 @@ -105,9 +105,9 @@ jmespath==1.0.1 ; python_version >= "3.13" and python_full_version < "4.0.0" \ legacy-cgi==2.6.3 ; python_version >= "3.13" and python_full_version < "4.0.0" \ --hash=sha256:4c119d6cb8e9d8b6ad7cc0ddad880552c62df4029622835d06dfd18f438a8154 \ --hash=sha256:6df2ea5ae14c71ef6f097f8b6372b44f6685283dc018535a75c924564183cdab -mypy-boto3-dynamodb==1.38.4 ; python_version >= "3.13" and python_full_version < "4.0.0" \ - --hash=sha256:5cf3787631e312b3d75f89a6cbbbd4ad786a76f5d565af023febf03fbf23c0b5 \ - --hash=sha256:6b29d89c649eeb1e894118bee002cb8b1304c78da735b1503aa08e46b0abfdec +mypy-boto3-dynamodb==1.39.0 ; python_version >= "3.13" and python_full_version < "4.0.0" \ + --hash=sha256:3a136f9d764fa5e1b2ff464fa9599533fd00e65affe47bd28a40d920ece707a4 \ + --hash=sha256:c3bafc7b4f8d59bac9a7436c7ccfb6fe32991bc7fc88c62264eaad06ae63f8a8 opentelemetry-api==1.34.1 ; python_version >= "3.13" and python_full_version < "4.0.0" \ --hash=sha256:64f0bd06d42824843731d05beea88d4d4b6ae59f9fe347ff7dfa2cc14233bbb3 \ --hash=sha256:b7df4cb0830d5a6c29ad0c0691dbae874d8daefa934b8b1d642de48323d32a8c diff --git a/src/activity-service/poetry.lock b/src/activity-service/poetry.lock index 753cd018..da4b44d5 100644 --- a/src/activity-service/poetry.lock +++ b/src/activity-service/poetry.lock @@ -48,14 +48,14 @@ tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" a [[package]] name = "aws-cdk-asset-awscli-v1" -version = "2.2.237" +version = "2.2.240" description = "A library that contains the AWS CLI for use in Lambda Layers" optional = false python-versions = "~=3.9" groups = ["dev"] files = [ - {file = "aws_cdk_asset_awscli_v1-2.2.237-py3-none-any.whl", hash = "sha256:642805ba143b35d11d5b5e80ab728db2ec8b894b2837b629ad95601e7e189e4c"}, - {file = "aws_cdk_asset_awscli_v1-2.2.237.tar.gz", hash = "sha256:e1dd0086af180c381d3ee81eb963a1f469627763e0507982b6f2d4075446bdf4"}, + {file = "aws_cdk_asset_awscli_v1-2.2.240-py3-none-any.whl", hash = "sha256:bcfa7124d40b9180697489d6875ed1c34a5dbb4db6eaad68148664c0d56b5af1"}, + {file = "aws_cdk_asset_awscli_v1-2.2.240.tar.gz", hash = "sha256:73a0787fedcc7e2010779593aa0c66398a4bc8e2291c918b07edc11ffd092612"}, ] [package.dependencies] @@ -118,18 +118,18 @@ typeguard = ">=2.13.3,<4.3.0" [[package]] name = "aws-cdk-lib" -version = "2.201.0" +version = "2.202.0" description = "Version 2 of the AWS Cloud Development Kit library" optional = false python-versions = "~=3.9" groups = ["dev"] files = [ - {file = "aws_cdk_lib-2.201.0-py3-none-any.whl", hash = "sha256:0856569d0ecb81414d08d987950261957d331486cd9daa7a115f2cf38b12c64d"}, - {file = "aws_cdk_lib-2.201.0.tar.gz", hash = "sha256:4dfdb59c5ff0341c48b1c91755e729a61d6508d015d2b9d545a825b9194eb1d2"}, + {file = "aws_cdk_lib-2.202.0-py3-none-any.whl", hash = "sha256:38183380494cef1fca47660536d704b9a2af461399580220939306f0c27f9db1"}, + {file = "aws_cdk_lib-2.202.0.tar.gz", hash = "sha256:cd01bff16595b8f0740b302c16ff9bcf64bf43fe035332052a0b4b89c5338710"}, ] [package.dependencies] -"aws-cdk.asset-awscli-v1" = "2.2.237" +"aws-cdk.asset-awscli-v1" = "2.2.240" "aws-cdk.asset-node-proxy-agent-v6" = ">=2.1.0,<3.0.0" "aws-cdk.cloud-assembly-schema" = ">=44.2.0,<45.0.0" constructs = ">=10.0.0,<11.0.0" @@ -234,18 +234,18 @@ extras = ["regex"] [[package]] name = "boto3" -version = "1.38.41" +version = "1.39.0" description = "The AWS SDK for Python" optional = false python-versions = ">=3.9" groups = ["main", "dev"] files = [ - {file = "boto3-1.38.41-py3-none-any.whl", hash = "sha256:6119e9f272b9f004f052ca78ce94d3fe10198bc159ae808f75c0e1b9c07518bd"}, - {file = "boto3-1.38.41.tar.gz", hash = "sha256:c6710fc533c8e1f5d1f025c74ffe1222c3659094cd51c076ec50c201a54c8f22"}, + {file = "boto3-1.39.0-py3-none-any.whl", hash = "sha256:6257f6f7bb87b66342564eab579ce1f0f63a4c1a6f701492f959e59bd7af68e5"}, + {file = "boto3-1.39.0.tar.gz", hash = "sha256:52a9f07fb9fa60ec6a2be07cd1586a97d8adae2be750121d4c032349cd113221"}, ] [package.dependencies] -botocore = ">=1.38.41,<1.39.0" +botocore = ">=1.39.0,<1.40.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.13.0,<0.14.0" @@ -254,14 +254,14 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.38.41" +version = "1.39.0" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.9" groups = ["main", "dev"] files = [ - {file = "botocore-1.38.41-py3-none-any.whl", hash = "sha256:06069a06f1352accb1f6c9505d6e323753627112be80a9d2e057c6d9c9779ffd"}, - {file = "botocore-1.38.41.tar.gz", hash = "sha256:98e3fed636ebb519320c4b2d078db6fa6099b052b4bb9b5c66632a5a7fe72507"}, + {file = "botocore-1.39.0-py3-none-any.whl", hash = "sha256:d8e72850d3450aeca355b654efb32c8370bf824c1945a61cad2395dc2688581e"}, + {file = "botocore-1.39.0.tar.gz", hash = "sha256:2b8701e529a80241b989d83262a629d0d91fbd7a06ded63ecc1c9d529a383d57"}, ] [package.dependencies] @@ -630,73 +630,73 @@ typeguard = ">=2.13.3,<4.3.0" [[package]] name = "ddtrace" -version = "3.9.3" +version = "3.9.4" description = "Datadog APM client library" optional = false python-versions = ">=3.8" groups = ["main"] files = [ - {file = "ddtrace-3.9.3-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:e0df3c294e0dfd222c3f040ddcade54e3f3d873fd42a2cc93b420dfa16bb252f"}, - {file = "ddtrace-3.9.3-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:a413ac19aba8c50bbe3a671dcc9886c5d30ae0514257ea05494235c35368c21f"}, - {file = "ddtrace-3.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab9312b0d417f297ef38305631ab85e75b20ec44b5fcf044b5b4cae28e24af2d"}, - {file = "ddtrace-3.9.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2533d4f05d4f4c0d1726c7926aecc2e97154954164c0a1e4c37d3b7660555203"}, - {file = "ddtrace-3.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09a0c7d6b13b361526b6306beabc0e8e397e22ca03125701071b3bdda80ebb4f"}, - {file = "ddtrace-3.9.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:695f76f481c7ed5794cfd266becdddd806304f410e5b698e9006b810687b8975"}, - {file = "ddtrace-3.9.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:42da87d7b78967b8f5e8adbe58edafd4e90b0431c6e37616c5faa4343ce5e77b"}, - {file = "ddtrace-3.9.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e3b227460c10fc8ec2f4c5548a0274a7750283b4402786c19c29d39f692ec6ff"}, - {file = "ddtrace-3.9.3-cp310-cp310-win32.whl", hash = "sha256:1137c3249bca6a29d40a916d85cc52171824c362d8eeef9440e72955e5d30d4e"}, - {file = "ddtrace-3.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:e1fb98f0e0899594d41867d1167a064eb5e9ec47cf607bdbc29eb9b59f4cd87f"}, - {file = "ddtrace-3.9.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:dc7504626bf9b881fe04413020b9d199ea66a6e9ea6b0210b6b9af5b9407749f"}, - {file = "ddtrace-3.9.3-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:9f2e5dd193b701651fe735cc02da5b3223b2ae9e4f6a028b10da47e6ba8600b1"}, - {file = "ddtrace-3.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60cc27d37abad390bd1e1c408368d30fd6348431bf2b8272e2ce77b521d4ece8"}, - {file = "ddtrace-3.9.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:662c2b3e1e5e2f6a56513e2bc8d370c60a8de532ba9a01e2159fee283bcd1784"}, - {file = "ddtrace-3.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c67d47b3833b957e7458bd21aafac174faaabada388bce80d7d054503963143"}, - {file = "ddtrace-3.9.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:842549c8f83befa8066423b696c026029168ab50fd27a11e24d4ef727b776174"}, - {file = "ddtrace-3.9.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f8aed9f3f4d7db0e8d4e5d3586a4d64535dc2a33861534aaf7b855377c3f959a"}, - {file = "ddtrace-3.9.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b9fcc0404fdd2a25bb035562e89c9bd27e7fe792ca3d50c0a66b5b946c8f113d"}, - {file = "ddtrace-3.9.3-cp311-cp311-win32.whl", hash = "sha256:97090dd988326a48403d4cc2aa11052de15d447e57a83c2335cd56e1c7560f04"}, - {file = "ddtrace-3.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:78e1ba4602328ccfee08f18c020c151a63c1882baf358dfecda32929f91f56ca"}, - {file = "ddtrace-3.9.3-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:ee54a29c53e2cbf8d07f57798f185280409415a249a968e904c887a12bbcf45e"}, - {file = "ddtrace-3.9.3-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:b2553355df4c8bac52041b2f08e1b692b03fe1068f9686fb400ae188356c303c"}, - {file = "ddtrace-3.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d5ef534db804ab4f84ef1fa30ad6144695eefadf7a0263f14b69418a4a5f2b6"}, - {file = "ddtrace-3.9.3-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:28f6623d13c13bdca3379862b53b11401d9056cd8af4b47881c3927b0c8ea2a0"}, - {file = "ddtrace-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30f5fbcd0940b35072c6d7fbfef810a362a3d580e9f2001dd1eb3f39527f7f83"}, - {file = "ddtrace-3.9.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:fec2d68b718d0f00f164b5ef4c803b89f7e1d0073c27f6e785c0de424db90e79"}, - {file = "ddtrace-3.9.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d1a73cd4d69546a0468feea7835e1c5dfe8efab2b237fd07e9c1749446630d3e"}, - {file = "ddtrace-3.9.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f075699a62a2db1356a22382fa667916a15857e9a12b249c4a5bc1c94e4c403f"}, - {file = "ddtrace-3.9.3-cp312-cp312-win32.whl", hash = "sha256:9b57a4a2ed7043aba1d859d7277b64d61dfc0687b431e081453e02186484ecf3"}, - {file = "ddtrace-3.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:5d8171be0bf47928037a5844bb0ca7820935b465d7bcec9fe022455f00b0f690"}, - {file = "ddtrace-3.9.3-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:b74b71588e004d6884474870252d409da9867fb7ce678e13f97f4ea36eb63444"}, - {file = "ddtrace-3.9.3-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:df8bca8d76c261f4c2fc0ea1cf30f537502fbd138c78609b94cd55243dabb57b"}, - {file = "ddtrace-3.9.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55d7b42d20e644cd819faf3fa41fc63ff6cbf85ce337d12d5e609a896c2b2e8e"}, - {file = "ddtrace-3.9.3-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:77c2af25dbb375f3780acf34fb5ba3253b756669400ecbf5f13db2a555094bd2"}, - {file = "ddtrace-3.9.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3344c4ebb3da8660df5aba758442d620100fad0e7d98b6702f4b06f1f3daba8"}, - {file = "ddtrace-3.9.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f559e8462c2be3e1fdd3abd8e4b041747e709e139d1a34359e6ca3a9aabd12ea"}, - {file = "ddtrace-3.9.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6e06f8379ef3c7d9d8234a1cbeb55c5af4ab763ddf4268381b5db67eb05fe397"}, - {file = "ddtrace-3.9.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d1a72898030cb323c496d0c7c69ce4cbcc5ae79c89d46ba8e707e9e3c442b6c3"}, - {file = "ddtrace-3.9.3-cp313-cp313-win32.whl", hash = "sha256:32219984d5c30fdc44a802b4cb9bab459e50361ea42cbca72d6d33c7041aef26"}, - {file = "ddtrace-3.9.3-cp313-cp313-win_amd64.whl", hash = "sha256:85888bfbd03ea0ec95d2cb6c35a5ffb5c00031ad813ef7e026d39a481b5f8f63"}, - {file = "ddtrace-3.9.3-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:2384d6c30b582c1402b43b0ace1162c40e82fcfa7d438783b8ee32c26ec135a1"}, - {file = "ddtrace-3.9.3-cp38-cp38-macosx_12_0_x86_64.whl", hash = "sha256:8edce9f0284931a4e976ec7cf16b260cdb57e209bcc0d258ba3fca568b8e73db"}, - {file = "ddtrace-3.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a29d358a5c5e382df25c06420acaf3ea4b4214e607da946de47f83f060e3e2e0"}, - {file = "ddtrace-3.9.3-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b6ee77918b1d50170632c9dfd83167f91682882c24fe3be787c150eecf9c78ec"}, - {file = "ddtrace-3.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b46233464b7537fe1842b7b8d1cb9a9dc572f2a767386100df1baa5017924bd"}, - {file = "ddtrace-3.9.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2d71f08970efce1cd8a3ecfc95a74d3b15da6c8870a5347693c100f64fc06984"}, - {file = "ddtrace-3.9.3-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:08b3a16ab2ad95aa65f16e1563769b6af22d3c3083c994c2761e1a7f22d28915"}, - {file = "ddtrace-3.9.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:9be2aff339f0ccca2f9d9fde19f1dd8117de6bd307a59ebd67198248bf3a2f41"}, - {file = "ddtrace-3.9.3-cp38-cp38-win32.whl", hash = "sha256:45b869826d91f3642bad362a7a4fd8450090bac14a70f3dedb9c804090cab541"}, - {file = "ddtrace-3.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:4cc6db6723e59bc8fb229ab177f3467dfe98aba650c5949d93fd18349f4d915a"}, - {file = "ddtrace-3.9.3-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:9d0d2d41ea05e1e60a3adff07670ac5e78c51d2c28c4b861cf6415a75da2f8e4"}, - {file = "ddtrace-3.9.3-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:b2c831a48e9ce4f9f1e40c9d5d7785710d8192aafdc51fd55f76919370382aea"}, - {file = "ddtrace-3.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:068d4cfbffa2d6bd19acb8fa2db74718310bf44a1d12f2d63b005d1e0fd93709"}, - {file = "ddtrace-3.9.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd88fbf82405c18acdfcf3dde28032caae16ae8c4fe3f52558866e6bf0533b7b"}, - {file = "ddtrace-3.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acd5ce9aa7131e46ebffb085c3cdf4847b3d7ae9ab8ba193f779188f3fccb001"}, - {file = "ddtrace-3.9.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:45bca3420798d345e1702b73fbce45f38f148c64374d3e2d18b7b115248a8ae9"}, - {file = "ddtrace-3.9.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:936ab058a43ab4ecf03d41e6199aeb0f76c82333eeef9ff5fae90106a7d71ab2"}, - {file = "ddtrace-3.9.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9ce3d9435218feada6f2d0e2cffa34e0ea7e376f6dd9f37011d199448ebc4e90"}, - {file = "ddtrace-3.9.3-cp39-cp39-win32.whl", hash = "sha256:19452e4024bb9b5e768d0fedfe461a9639a2f2a2077b31a2e0bd7128529bbb4c"}, - {file = "ddtrace-3.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:8e83909c4961b60221ec1bd9f8ba98bec0c9e4717c47faf4fad9d60e4f0a1b96"}, - {file = "ddtrace-3.9.3.tar.gz", hash = "sha256:137f84cbf599ace230d4d842e520910a6dd9c2a19022c80c8b55583da070fbac"}, + {file = "ddtrace-3.9.4-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:f59b3623fc792f4b820db740ba77e51c2169d9bbcc9d04894a1b698aa5ce0147"}, + {file = "ddtrace-3.9.4-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:16671001252cf7bb7f95d0526dc53a28b3ec878ff2b8e41ddce94e6c39acf557"}, + {file = "ddtrace-3.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb80929280c6a847e4282259fec9f0357e446844eec9ef3ae4db88aebb284837"}, + {file = "ddtrace-3.9.4-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d9268c5728847383c1ef060848ae8bd6caf570d67fee071ebc21b1d1daa18f36"}, + {file = "ddtrace-3.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8db657d82ed2a18de07914f27a4bacd90256fb613436506be980359de1c60ceb"}, + {file = "ddtrace-3.9.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b1a9ee8ecee85a1e695641aa0267f98c6e9e0a9cb45d86a4b0cd15ae73eca342"}, + {file = "ddtrace-3.9.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:09805165f5680b7257ccb5f3f7da6407c14327250f9a318c8029d03a21271c93"}, + {file = "ddtrace-3.9.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1d07be09e53fdcd71f2c30ac3cc3ace9f6bbad5c8185728dee7292857935531c"}, + {file = "ddtrace-3.9.4-cp310-cp310-win32.whl", hash = "sha256:39e937b9b91a502fc9cf7c124ee5dcb914566a2421b521561b71d3790045a101"}, + {file = "ddtrace-3.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:c2c4891fb42a8bb23ef2a787dc14c00047d0f46536eb0eb116a14a4fce12c919"}, + {file = "ddtrace-3.9.4-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:3df90869f0912778a24e785778b09dbd8a01d51f86ebe49632766f38567f3adf"}, + {file = "ddtrace-3.9.4-cp311-cp311-macosx_12_0_x86_64.whl", hash = "sha256:9923b0e488b5d7990618ea10034d81148b53aaec10dc567c962927d08ee877c5"}, + {file = "ddtrace-3.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2b872f7bfb0a17ecef8fa207478055f1b27d2f5c2b9455e9ee20316ed944e32"}, + {file = "ddtrace-3.9.4-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68c15a73567e699c8c1441fa2cc964ceddc9379ee0efe5d2d2342d7456f6cf66"}, + {file = "ddtrace-3.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e70de00f2e4d4d5fc5c25430c58f5c2e7a2169dc5995a61338e07d540dcea9e"}, + {file = "ddtrace-3.9.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ef24eb6750b7004492e0ce4aacbbd4969aad11a3a6eb164d2e3c2ce9a6bf3829"}, + {file = "ddtrace-3.9.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:cdd1fcf023d12cb3bccb738428434a56d73e8bdc536de131ff3f361bd0843a5c"}, + {file = "ddtrace-3.9.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:73c1614cbc3b77b72e049729e22cec752c8ac80142ad13cd80755d565763f747"}, + {file = "ddtrace-3.9.4-cp311-cp311-win32.whl", hash = "sha256:20f255dd34dcf32939b7f54200014832b8875329ec9216b41ab9ecd481301dae"}, + {file = "ddtrace-3.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:bb986454b7a066d1d25095b473a08e44dc2d37d37648a13784ad8e0a56f6b301"}, + {file = "ddtrace-3.9.4-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:fda91bc31cc0184d651c04637620903d4d4cad224ff189686034495bf052e96d"}, + {file = "ddtrace-3.9.4-cp312-cp312-macosx_12_0_x86_64.whl", hash = "sha256:afa927dba6e214c7ddf52205ca5f476712ea05a69408a3a68adb11a174aedd1c"}, + {file = "ddtrace-3.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15127303354075dc8bffe1118243041522032416b5c0f71ed5dac8f934f955d5"}, + {file = "ddtrace-3.9.4-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bb80ba47552d52f82da947d9dcbbfeb6c3ef24c4932f045d9c1bc58c15fe49e"}, + {file = "ddtrace-3.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7258bd2e9532daf55059ec077395db1ab284493a8a2d6001fad247c5f8a57f2"}, + {file = "ddtrace-3.9.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7fa77642065489bc619f5af750e483076955accbb8d230f477e5f647fe203d81"}, + {file = "ddtrace-3.9.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d635f13e143d338befd6655490ca634dc7df1f647cec6f6240e7ffc045afb4ca"}, + {file = "ddtrace-3.9.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1d1bbeda4c7a7f77fc5f3cf7d95e11edd5c441db47bfd3554f128c8482a1d7ab"}, + {file = "ddtrace-3.9.4-cp312-cp312-win32.whl", hash = "sha256:73d517e8852b947e4fba727e620cc6d549dd19b4f2bc3fefb37fc1773c31b37c"}, + {file = "ddtrace-3.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:2c8f9a9d542ce5566505dd84d212e636607bcd7ab40aa5bf512ac7b29d25230c"}, + {file = "ddtrace-3.9.4-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:0689955ddab33f8d9adb87114b97d64eed05b8017a288e1c6651b06f72406226"}, + {file = "ddtrace-3.9.4-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:8601eb960fab75b7cafc1f976097e244c132868de116b31de50209d2818ae796"}, + {file = "ddtrace-3.9.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:728f0110341353bb1cb425ab93877c2ca2ddab2f096f0ec1e50c8e26c41c7364"}, + {file = "ddtrace-3.9.4-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01abb4066b2ffd8125fe024571f20037653e472bbefafef3809d7a7e898ad8ee"}, + {file = "ddtrace-3.9.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82773444cd8d268026a64905b3db7a32bfed03b534051d8244d111ad301f0345"}, + {file = "ddtrace-3.9.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:28fd5c7aaf30d7b88a5ef43f4a80f7a54dceee137a76bda1d9c058f23296ab02"}, + {file = "ddtrace-3.9.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6576d121cdf07d24e067f79511e3890595811a635d2ac643eefd0cbdcf3ec5f1"}, + {file = "ddtrace-3.9.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:944c057f572e2c7a36e71b31a8d1d87306e200001b1fae36319699552a9546bc"}, + {file = "ddtrace-3.9.4-cp313-cp313-win32.whl", hash = "sha256:bb2472167e47826145be93606335dbf8c49138dba50ea4cc881ad52c834fc0d3"}, + {file = "ddtrace-3.9.4-cp313-cp313-win_amd64.whl", hash = "sha256:5251d3c3c60ef834b53c838714ac38b41dec30e0dbe042eddd2f06c8f5b356d2"}, + {file = "ddtrace-3.9.4-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:720c3802ddd80d2a4b441d1ed7b0a7c40ab7facd8f92dd7675e83533b2aa7759"}, + {file = "ddtrace-3.9.4-cp38-cp38-macosx_12_0_x86_64.whl", hash = "sha256:325cd3a240845e45d6288f6af252028a418419a11e64af4d716450aee6746830"}, + {file = "ddtrace-3.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:787d5c6354e01e2374df8c1c0d41cad8abdb3b265ee27f640396e9a932d0adb2"}, + {file = "ddtrace-3.9.4-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:918e9f538d6ff715fe63e65889aa9d4b7cfdf7c091492ba0ff7e8b2734751975"}, + {file = "ddtrace-3.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d72f980e14f46474bef30f9526b17a733acc1f1dd6fa97a869ed1ec9a0bce42"}, + {file = "ddtrace-3.9.4-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:b7c9b012cd6f13cfc62eda62cf2af2e14696cd33212434f8a2cb6c0e09bc9a4c"}, + {file = "ddtrace-3.9.4-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:6343a214231bc4413304e4eaf5cdb23c20eab5945d2ca2789c1e37b9dd814f13"}, + {file = "ddtrace-3.9.4-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:62f6b2e0b7ad230a3336b328e9efb5eeb7fbb4838b1aa1374a33d82f5a6cec5e"}, + {file = "ddtrace-3.9.4-cp38-cp38-win32.whl", hash = "sha256:f63e7a4ca88251304e8a6a757daa944a86b1104602176196eb73bd0da3ac5701"}, + {file = "ddtrace-3.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:397c9c85932e5d9a7d5792faa4311d2db54ef33ed65cfa7019a14567c8708105"}, + {file = "ddtrace-3.9.4-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:2567cf92ee176b94c36812a0468a168c28bcb13f2ad737b39313e1ca4902db12"}, + {file = "ddtrace-3.9.4-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:de6db7d26ff7327a44df39ddc79f5caacdee882dea5f2dce2821af85afdbf245"}, + {file = "ddtrace-3.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f50321e6dcbea49cfd5e1b6c857cc0dc16408044f02e1e48f88c73a3ea1a6933"}, + {file = "ddtrace-3.9.4-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cc81653a37755a2034d55c0b88847b8533a1cfdc2e8ac0e5b779ec15acd43f7f"}, + {file = "ddtrace-3.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c778db5e067c72e186e693739a0bf3ce30258d44393959695e65d25fe442a586"}, + {file = "ddtrace-3.9.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2d5c9e2e1cd12312776809adf0a8d04b8c52de3a84e74dcacc882d8875519469"}, + {file = "ddtrace-3.9.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e4c29497889588a68b508469f1c307b9506665481ac16c782b4510e47cb611d3"}, + {file = "ddtrace-3.9.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1ee655550a4442e58028527b47677c45bbddf7ed70a31b1991a0574d85446c17"}, + {file = "ddtrace-3.9.4-cp39-cp39-win32.whl", hash = "sha256:a8733a4e1a500a740792441fb288e39fa5a4aede7362d0d5dad6e1051d20da84"}, + {file = "ddtrace-3.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:370ab3c5b1590402802ac344b1d192fad815006e7c379d5effc4aec3289ad502"}, + {file = "ddtrace-3.9.4.tar.gz", hash = "sha256:e1a0bc433c52e396452dbf251710d812713649c135d856c98e2e23955237e68b"}, ] [package.dependencies] @@ -1303,14 +1303,14 @@ reports = ["lxml"] [[package]] name = "mypy-boto3-dynamodb" -version = "1.38.4" -description = "Type annotations for boto3 DynamoDB 1.38.4 service generated with mypy-boto3-builder 8.10.1" +version = "1.39.0" +description = "Type annotations for boto3 DynamoDB 1.39.0 service generated with mypy-boto3-builder 8.11.0" optional = false python-versions = ">=3.8" groups = ["main"] files = [ - {file = "mypy_boto3_dynamodb-1.38.4-py3-none-any.whl", hash = "sha256:6b29d89c649eeb1e894118bee002cb8b1304c78da735b1503aa08e46b0abfdec"}, - {file = "mypy_boto3_dynamodb-1.38.4.tar.gz", hash = "sha256:5cf3787631e312b3d75f89a6cbbbd4ad786a76f5d565af023febf03fbf23c0b5"}, + {file = "mypy_boto3_dynamodb-1.39.0-py3-none-any.whl", hash = "sha256:3a136f9d764fa5e1b2ff464fa9599533fd00e65affe47bd28a40d920ece707a4"}, + {file = "mypy_boto3_dynamodb-1.39.0.tar.gz", hash = "sha256:c3bafc7b4f8d59bac9a7436c7ccfb6fe32991bc7fc88c62264eaad06ae63f8a8"}, ] [[package]] @@ -2279,4 +2279,4 @@ type = ["pytest-mypy"] [metadata] lock-version = "2.1" python-versions = "^3.13.0" -content-hash = "02c3672f1bc86461c1be729165ac3be43cbc957867a56823043591faac605364" +content-hash = "42d37b6fd873daf577bc96174a98389ec45dcd92543be5e3b6981fcb37165423" diff --git a/src/activity-service/pyproject.toml b/src/activity-service/pyproject.toml index ecf7330a..f5035cfd 100644 --- a/src/activity-service/pyproject.toml +++ b/src/activity-service/pyproject.toml @@ -21,16 +21,16 @@ python = "^3.13.0" pydantic = {version = "^2.0.3"} email-validator = {version = "*"} aws-lambda-powertools = {extras = ["tracer"],version = "^3.15.1"} -mypy-boto3-dynamodb = "*" +mypy-boto3-dynamodb = "^1.39.0" cachetools = "*" -boto3 = "^1.38.41" +boto3 = "^1.39.0" aws-lambda-env-modeler = "*" -ddtrace = "3.9.3" +ddtrace = "3.9.4" [tool.poetry.group.dev.dependencies] # CDK activity-service-cdk = {path = "cdk", develop = true} -aws-cdk-lib = ">=2.201.0" +aws-cdk-lib = ">=2.202.0" datadog-cdk-constructs-v2 = "^2.6.0" constructs = ">=10.0.0" cdk-nag = ">2.0.0" diff --git a/src/activity-service/template.yaml b/src/activity-service/template.yaml new file mode 100644 index 00000000..ee6543c0 --- /dev/null +++ b/src/activity-service/template.yaml @@ -0,0 +1,604 @@ +# +# Unless explicitly stated otherwise all files in this repository are licensed +# under the Apache License Version 2.0. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2024 Datadog, Inc. +# + +AWSTemplateFormatVersion: '2010-09-09' +Transform: + - AWS::Serverless-2016-10-31 + - Name: DatadogServerless + Parameters: + stackName: !Ref "AWS::StackName" + apiKey: !Ref DDApiKey + pythonLayerVersion: 111 + extensionLayerVersion: 82 + service: !Ref ServiceName + env: !Ref Env + version: !Ref CommitHash + site: !Ref DDSite + captureLambdaPayload: true +Description: Activity Service - Serverless activity tracking service built with AWS SAM + +Conditions: + IsNonProdEnvironment: !Not [!Equals [!Ref Env, prod]] + IsIntegratedEnvironment: !Or + - !Equals ["dev", !Ref Env] + - !Equals ["prod", !Ref Env] + IsNotIntegratedEnvironment: !And + - !Not [!Equals [!Ref Env, prod]] + - !Not [!Equals [!Ref Env, dev]] + +Parameters: + ServiceName: + Type: String + Default: OrdersService + Env: + Type: String + Default: dev + CommitHash: + Type: String + Default: latest + DDSite: + Type: String + DDApiKey: + Type: String + +Globals: + Function: + Runtime: python3.13 + Timeout: 29 + MemorySize: 512 + Environment: + Variables: + POWERTOOLS_SERVICE_NAME: ActivityService + LOG_LEVEL: INFO + DD_CAPTURE_LAMBDA_PAYLOAD: true + DD_COLD_START_TRACING: true + DD_TRACE_ENABLED: true + +Resources: + # DynamoDB Tables + ActivitiesTable: + Type: AWS::DynamoDB::Table + Properties: + TableName: !Sub "Activities-${Env}" + BillingMode: PAY_PER_REQUEST + AttributeDefinitions: + - AttributeName: PK + AttributeType: S + - AttributeName: SK + AttributeType: S + KeySchema: + - AttributeName: PK + KeyType: HASH + - AttributeName: SK + KeyType: RANGE + PointInTimeRecoverySpecification: + PointInTimeRecoveryEnabled: true + DeletionProtectionEnabled: false + + IdempotencyTable: + Type: AWS::DynamoDB::Table + Properties: + TableName: !Sub "ActivitiesIdempotency-${Env}" + BillingMode: PAY_PER_REQUEST + AttributeDefinitions: + - AttributeName: id + AttributeType: S + KeySchema: + - AttributeName: id + KeyType: HASH + TimeToLiveSpecification: + AttributeName: expiration + Enabled: true + PointInTimeRecoverySpecification: + PointInTimeRecoveryEnabled: true + DeletionProtectionEnabled: false + + # SQS Queues + ActivityDeadLetterQueue: + Type: AWS::SQS::Queue + Properties: + QueueName: !Sub "ActivityService-activity-dlq-${Env}" + MessageRetentionPeriod: 1209600 # 14 days + + ActivityQueue: + Type: AWS::SQS::Queue + Properties: + QueueName: !Sub "ActivityService-activity-queue-${Env}" + RedrivePolicy: + deadLetterTargetArn: !GetAtt ActivityDeadLetterQueue.Arn + maxReceiveCount: 3 + + # EventBridge Custom Bus + ActivityEventBus: + Type: AWS::Events::EventBus + Properties: + Name: !Sub "ActivityService-events-${Env}" + + # Common Lambda Layer + CommonLayer: + Type: AWS::Serverless::LayerVersion + Properties: + LayerName: !Sub "ActivityService-common-${Env}" + Description: "Common dependencies layer for Activity Service" + ContentUri: .build/common_layer/ + CompatibleRuntimes: + - python3.13 + Metadata: + BuildMethod: python3.13 + + # Lambda IAM Role + LambdaExecutionRole: + Type: AWS::IAM::Role + Properties: + RoleName: !Sub "SAM-ActivityService-ServiceRole-${Env}" + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: lambda.amazonaws.com + Action: sts:AssumeRole + ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole + Policies: + - PolicyName: DynamoDBAccess + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - dynamodb:PutItem + - dynamodb:GetItem + - dynamodb:Query + Resource: !GetAtt ActivitiesTable.Arn + - Effect: Allow + Action: + - dynamodb:PutItem + - dynamodb:GetItem + - dynamodb:UpdateItem + - dynamodb:DeleteItem + Resource: !GetAtt IdempotencyTable.Arn + - PolicyName: AppConfigAccess + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - appconfig:GetLatestConfiguration + - appconfig:StartConfigurationSession + Resource: '*' + - PolicyName: AllowSQSAccess + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - sqs:ChangeMessageVisibility + - sqs:ChangeMessageVisibilityBatch + - sqs:DeleteMessage + - sqs:DeleteMessageBatch + - sqs:GetQueueAttributes + - sqs:ReceiveMessage + Resource: !GetAtt ActivityQueue.Arn + + # Lambda Functions + GetActivityFunction: + Type: AWS::Serverless::Function + Properties: + FunctionName: !Sub "ActivityService-GetActivity-${Env}" + CodeUri: .build/lambdas/ + Handler: activity_service.handlers.handle_get_activity.lambda_handler + Role: !GetAtt LambdaExecutionRole.Arn + Layers: + - !Ref CommonLayer + Environment: + Variables: + TABLE_NAME: !Ref ActivitiesTable + IDEMPOTENCY_TABLE_NAME: !Ref IdempotencyTable + Events: + ApiEvent: + Type: Api + Properties: + RestApiId: !Ref ActivityApi + Path: /api/activity/{entity_type}/{entity_id} + Method: GET + + HandleEventsFunction: + Type: AWS::Serverless::Function + Properties: + FunctionName: !Sub "ActivityService-HandleEvents-${Env}" + CodeUri: .build/lambdas/ + Handler: activity_service.handlers.create_activity.lambda_handler + Role: !GetAtt LambdaExecutionRole.Arn + Layers: + - !Ref CommonLayer + Environment: + Variables: + TABLE_NAME: !Ref ActivitiesTable + IDEMPOTENCY_TABLE_NAME: !Ref IdempotencyTable + Events: + SQSEvent: + Type: SQS + Properties: + Queue: !GetAtt ActivityQueue.Arn + BatchSize: 10 + FunctionResponseTypes: + - ReportBatchItemFailures + + # API Gateway + ActivityApi: + Type: AWS::Serverless::Api + Properties: + Name: !Sub "Activity Service Rest API - ${Env}" + StageName: Prod + Description: "This service handles /api/activity requests" + + # EventBridge Rules for Event Subscriptions + ProductCreatedRule: + Type: AWS::Events::Rule + Properties: + Name: !Sub "activity_product_productCreated_v1-${Env}" + EventBusName: !Ref ActivityEventBus + EventPattern: + detail-type: + - "product.productCreated.v1" + Targets: + - Arn: !GetAtt ActivityQueue.Arn + Id: "ActivityQueueTarget" + + ProductUpdatedRule: + Type: AWS::Events::Rule + Properties: + Name: !Sub "activity_product_productUpdated_v1-${Env}" + EventBusName: !Ref ActivityEventBus + EventPattern: + detail-type: + - "product.productUpdated.v1" + Targets: + - Arn: !GetAtt ActivityQueue.Arn + Id: "ActivityQueueTarget" + + ProductDeletedRule: + Type: AWS::Events::Rule + Properties: + Name: !Sub "activity_product_productDeleted_v1-${Env}" + EventBusName: !Ref ActivityEventBus + EventPattern: + detail-type: + - "product.productDeleted.v1" + Targets: + - Arn: !GetAtt ActivityQueue.Arn + Id: "ActivityQueueTarget" + + UserCreatedRule: + Type: AWS::Events::Rule + Properties: + Name: !Sub "activity_users_userCreated_v1-${Env}" + EventBusName: !Ref ActivityEventBus + EventPattern: + detail-type: + - "users.userCreated.v1" + Targets: + - Arn: !GetAtt ActivityQueue.Arn + Id: "ActivityQueueTarget" + + OrderCreatedRule: + Type: AWS::Events::Rule + Properties: + Name: !Sub "activity_orders_orderCreated_v1-${Env}" + EventBusName: !Ref ActivityEventBus + EventPattern: + detail-type: + - "orders.orderCreated.v1" + Targets: + - Arn: !GetAtt ActivityQueue.Arn + Id: "ActivityQueueTarget" + + OrderConfirmedRule: + Type: AWS::Events::Rule + Properties: + Name: !Sub "activity_orders_orderConfirmed_v1-${Env}" + EventBusName: !Ref ActivityEventBus + EventPattern: + detail-type: + - "orders.orderConfirmed.v1" + Targets: + - Arn: !GetAtt ActivityQueue.Arn + Id: "ActivityQueueTarget" + + OrderCompletedRule: + Type: AWS::Events::Rule + Properties: + Name: !Sub "activity_orders_orderCompleted_v1-${Env}" + EventBusName: !Ref ActivityEventBus + EventPattern: + detail-type: + - "orders.orderCompleted.v1" + Targets: + - Arn: !GetAtt ActivityQueue.Arn + Id: "ActivityQueueTarget" + + StockUpdatedRule: + Type: AWS::Events::Rule + Properties: + Name: !Sub "activity_inventory_stockUpdated_v1-${Env}" + EventBusName: !Ref ActivityEventBus + EventPattern: + detail-type: + - "inventory.stockUpdated.v1" + Targets: + - Arn: !GetAtt ActivityQueue.Arn + Id: "ActivityQueueTarget" + + StockReservedRule: + Type: AWS::Events::Rule + Properties: + Name: !Sub "activity_inventory_stockReserved_v1-${Env}" + EventBusName: !Ref ActivityEventBus + EventPattern: + detail-type: + - "inventory.stockReserved.v1" + Targets: + - Arn: !GetAtt ActivityQueue.Arn + Id: "ActivityQueueTarget" + + StockReservationFailedRule: + Type: AWS::Events::Rule + Properties: + Name: !Sub "activity_inventory_stockReservationFailed_v1-${Env}" + EventBusName: !Ref ActivityEventBus + EventPattern: + detail-type: + - "inventory.stockReservationFailed.v1" + Targets: + - Arn: !GetAtt ActivityQueue.Arn + Id: "ActivityQueueTarget" + + # SQS Queue Policies to allow EventBridge to send messages + ActivityQueuePolicy: + Type: AWS::SQS::QueuePolicy + Properties: + Queues: + - !Ref ActivityQueue + PolicyDocument: + Statement: + - Effect: Allow + Principal: + Service: events.amazonaws.com + Action: + - sqs:SendMessage + Resource: !GetAtt ActivityQueue.Arn + + # SSM Parameters + ActivityApiEndpointParameter: + Type: AWS::SSM::Parameter + Properties: + Name: !Sub "/${Env}/ActivityService/api-endpoint" + Type: String + Value: !Sub "https://${ActivityApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/" + + ActivityEventBusArnParameter: + Type: AWS::SSM::Parameter + Properties: + Name: !Sub "/${Env}/ActivityService/event-bus-arn" + Type: String + Value: !GetAtt ActivityEventBus.Arn + + ActivityEventBusNameParameter: + Type: AWS::SSM::Parameter + Properties: + Name: !Sub "/${Env}/ActivityService/event-bus-name" + Type: String + Value: !Ref ActivityEventBus + + # JWT Secret (conditional based on environment) + JwtSecretAccessKey: + Type: AWS::SSM::Parameter + Condition: IsNotIntegratedEnvironment + Properties: + Name: !Sub "/${Env}/ActivityService/secret-access-key" + Type: String + Value: "This is a sample secret key that should not be used in production" + + ################################################ + ######## Public Event Subscriptions ############ + ################################################ + SharedEventBusToActivityServiceEventBusRole: + Type: AWS::IAM::Role + Condition: IsIntegratedEnvironment + Properties: + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + Service: + - events.amazonaws.com + Action: + - sts:AssumeRole + Path: / + Policies: + - PolicyName: allow-eb-publish + PolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - "events:PutEvents" + Resource: [!GetAtt ActivityEventBus.Arn] + + # EventBridge Rules for Event Subscriptions + SharedProductCreatedRule: + Type: AWS::Events::Rule + Condition: IsIntegratedEnvironment + Properties: + Name: !Sub "shared_activity_product_productCreated_v1-${Env}" + EventBusName: !Sub "{{resolve:ssm:/${Env}/shared/event-bus-name:1}}" + EventPattern: + detail-type: + - "product.productCreated.v1" + Targets: + - Id: ActivityServiceEventBus + Arn: !GetAtt ActivityEventBus.Arn + RoleArn: !GetAtt SharedEventBusToActivityServiceEventBusRole.Arn + + SharedProductUpdatedRule: + Type: AWS::Events::Rule + Condition: IsIntegratedEnvironment + Properties: + Name: !Sub "shared_activity_product_productUpdated_v1-${Env}" + EventBusName: !Sub "{{resolve:ssm:/${Env}/shared/event-bus-name:1}}" + EventPattern: + detail-type: + - "product.productUpdated.v1" + Targets: + - Id: ActivityServiceEventBus + Arn: !GetAtt ActivityEventBus.Arn + RoleArn: !GetAtt SharedEventBusToActivityServiceEventBusRole.Arn + + SharedProductDeletedRule: + Type: AWS::Events::Rule + Condition: IsIntegratedEnvironment + Properties: + Name: !Sub "shared_activity_product_productDeleted_v1-${Env}" + EventBusName: !Sub "{{resolve:ssm:/${Env}/shared/event-bus-name:1}}" + EventPattern: + detail-type: + - "product.productDeleted.v1" + Targets: + - Id: ActivityServiceEventBus + Arn: !GetAtt ActivityEventBus.Arn + RoleArn: !GetAtt SharedEventBusToActivityServiceEventBusRole.Arn + + SharedUserCreatedRule: + Type: AWS::Events::Rule + Condition: IsIntegratedEnvironment + Properties: + Name: !Sub "shared_activity_users_userCreated_v1-${Env}" + EventBusName: !Sub "{{resolve:ssm:/${Env}/shared/event-bus-name:1}}" + EventPattern: + detail-type: + - "users.userCreated.v1" + Targets: + - Id: ActivityServiceEventBus + Arn: !GetAtt ActivityEventBus.Arn + RoleArn: !GetAtt SharedEventBusToActivityServiceEventBusRole.Arn + + SharedOrderCreatedRule: + Type: AWS::Events::Rule + Condition: IsIntegratedEnvironment + Properties: + Name: !Sub "shared_activity_orders_orderCreated_v1-${Env}" + EventBusName: !Sub "{{resolve:ssm:/${Env}/shared/event-bus-name:1}}" + EventPattern: + detail-type: + - "orders.orderCreated.v1" + Targets: + - Id: ActivityServiceEventBus + Arn: !GetAtt ActivityEventBus.Arn + RoleArn: !GetAtt SharedEventBusToActivityServiceEventBusRole.Arn + + SharedOrderConfirmedRule: + Type: AWS::Events::Rule + Condition: IsIntegratedEnvironment + Properties: + Name: !Sub "shared_activity_orders_orderConfirmed_v1-${Env}" + EventBusName: !Sub "{{resolve:ssm:/${Env}/shared/event-bus-name:1}}" + EventPattern: + detail-type: + - "orders.orderConfirmed.v1" + Targets: + - Id: ActivityServiceEventBus + Arn: !GetAtt ActivityEventBus.Arn + RoleArn: !GetAtt SharedEventBusToActivityServiceEventBusRole.Arn + + SharedOrderCompletedRule: + Type: AWS::Events::Rule + Condition: IsIntegratedEnvironment + Properties: + Name: !Sub "shared_activity_orders_orderCompleted_v1-${Env}" + EventBusName: !Sub "{{resolve:ssm:/${Env}/shared/event-bus-name:1}}" + EventPattern: + detail-type: + - "orders.orderCompleted.v1" + Targets: + - Id: ActivityServiceEventBus + Arn: !GetAtt ActivityEventBus.Arn + RoleArn: !GetAtt SharedEventBusToActivityServiceEventBusRole.Arn + + SharedStockUpdatedRule: + Type: AWS::Events::Rule + Condition: IsIntegratedEnvironment + Properties: + Name: !Sub "shared_activity_inventory_stockUpdated_v1-${Env}" + EventBusName: !Sub "{{resolve:ssm:/${Env}/shared/event-bus-name:1}}" + EventPattern: + detail-type: + - "inventory.stockUpdated.v1" + Targets: + - Id: ActivityServiceEventBus + Arn: !GetAtt ActivityEventBus.Arn + RoleArn: !GetAtt SharedEventBusToActivityServiceEventBusRole.Arn + + SharedStockReservedRule: + Type: AWS::Events::Rule + Condition: IsIntegratedEnvironment + Properties: + Name: !Sub "shared_activity_inventory_stockReserved_v1-${Env}" + EventBusName: !Sub "{{resolve:ssm:/${Env}/shared/event-bus-name:1}}" + EventPattern: + detail-type: + - "inventory.stockReserved.v1" + Targets: + - Id: ActivityServiceEventBus + Arn: !GetAtt ActivityEventBus.Arn + RoleArn: !GetAtt SharedEventBusToActivityServiceEventBusRole.Arn + + SharedStockReservationFailedRule: + Type: AWS::Events::Rule + Condition: IsIntegratedEnvironment + Properties: + Name: !Sub "shared_activity_inventory_stockReservationFailed_v1-${Env}" + EventBusName: !Sub "{{resolve:ssm:/${Env}/shared/event-bus-name:1}}" + EventPattern: + detail-type: + - "inventory.stockReservationFailed.v1" + Targets: + - Id: ActivityServiceEventBus + Arn: !GetAtt ActivityEventBus.Arn + RoleArn: !GetAtt SharedEventBusToActivityServiceEventBusRole.Arn + +Outputs: + ApiEndpoint: + Description: "API Gateway endpoint URL" + Value: !Sub "https://${ActivityApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/" + Export: + Name: !Sub "${AWS::StackName}-ApiEndpoint" + + ActivitiesTableName: + Description: "DynamoDB Activities Table Name" + Value: !Ref ActivitiesTable + Export: + Name: !Sub "${AWS::StackName}-ActivitiesTable" + + IdempotencyTableName: + Description: "DynamoDB Idempotency Table Name" + Value: !Ref IdempotencyTable + Export: + Name: !Sub "${AWS::StackName}-IdempotencyTable" + + ActivityEventBusName: + Description: "EventBridge Bus Name" + Value: !Ref ActivityEventBus + Export: + Name: !Sub "${AWS::StackName}-EventBus" + + ActivityQueueUrl: + Description: "SQS Queue URL" + Value: !Ref ActivityQueue + Export: + Name: !Sub "${AWS::StackName}-ActivityQueue" \ No newline at end of file From 00592b346d219ccbff201287bf76a4e2b1fb4da9 Mon Sep 17 00:00:00 2001 From: James Eastham Date: Tue, 1 Jul 2025 16:08:02 +0100 Subject: [PATCH 3/6] fix: update tracer download (#356) --- src/order-service/src/Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/order-service/src/Dockerfile b/src/order-service/src/Dockerfile index ee48054b..1b9c508c 100644 --- a/src/order-service/src/Dockerfile +++ b/src/order-service/src/Dockerfile @@ -4,8 +4,7 @@ WORKDIR /app FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build # Download the latest version of the tracer but don't install yet -RUN TRACER_VERSION=$(curl -s \https://api.github.com/repos/DataDog/dd-trace-dotnet/releases/latest | grep tag_name | cut -d '"' -f 4 | cut -c2-) \ - && curl -Lo /tmp/datadog-dotnet-apm.deb https://github.com/DataDog/dd-trace-dotnet/releases/download/v${TRACER_VERSION}/datadog-dotnet-apm_${TRACER_VERSION}_amd64.deb +RUN curl -Lo /tmp/datadog-dotnet-apm.deb https://github.com/DataDog/dd-trace-dotnet/releases/download/v3.19.0/datadog-dotnet-apm_3.19.0_amd64.deb WORKDIR /src From 482f0d6afb971f9b2978a3da51b4900442126089 Mon Sep 17 00:00:00 2001 From: James Eastham Date: Tue, 1 Jul 2025 16:57:13 +0100 Subject: [PATCH 4/6] chore: update dependabot references (#357) --- .github/dependabot.yml | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 49527993..c0a5c910 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -2,32 +2,43 @@ version: 2 updates: - package-ecosystem: "maven" - directory: "/src/java" + directory: "/src/inventory-service" schedule: interval: "monthly" - package-ecosystem: "npm" directories: - - "/src/nodejs" - - "/src/rust" + - "/src/loyalty-point-service" + - "/src/pricing-service" + - "/src/user-management-service" schedule: interval: "monthly" - package-ecosystem: "nuget" - directory: "/src/dotnet" + directory: "/src/order-service" schedule: interval: "monthly" - package-ecosystem: "terraform" directories: - - "/src/java/infra" - - "/src/nodejs/infra" - - "/src/dotnet/infra" + - "/src/inventory-service/infra" + - "/src/loyalty-point-service/infra" + - "/src/pricing-service/infra" + - "/src/user-management-service/infra" + - "/src/order-service/infra" + - "/src/product-management-service/infra" + - "/src/activity-service/infra" schedule: interval: "monthly" - package-ecosystem: "cargo" directories: - - "/src/rust" + - "/src/user-management-service" + schedule: + interval: "monthly" + + - package-ecosystem: "pip" + directories: + - "/src/activity-service" schedule: interval: "monthly" From c726bfd5c854795c4e61e066b471bca05b5d4227 Mon Sep 17 00:00:00 2001 From: James Eastham Date: Tue, 1 Jul 2025 17:47:14 +0100 Subject: [PATCH 5/6] chore: update codeowners (#385) --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 5edcbaf3..81d3809e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @DataDog/serverless-onboarding-enablement +* @jeastham1993 From 9418235959ca84a32f457ff8868962f4db7b627e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Jul 2025 18:35:28 +0100 Subject: [PATCH 6/6] chore(deps): bump @types/jsonwebtoken from 9.0.9 to 9.0.10 in /src/pricing-service (#384) * chore(deps): bump @types/jsonwebtoken in /src/pricing-service Bumps [@types/jsonwebtoken](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jsonwebtoken) from 9.0.9 to 9.0.10. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jsonwebtoken) --- updated-dependencies: - dependency-name: "@types/jsonwebtoken" dependency-version: 9.0.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * fix: update configure credentials action step --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: james.eastham --- .github/workflows/deploy-activity-service.yml | 4 +- .github/workflows/deploy-build-image.yml | 2 +- .../workflows/deploy-inventory-service.yml | 8 +- .github/workflows/deploy-loyalty-service.yml | 6 +- .github/workflows/deploy-orders-service.yml | 8 +- .github/workflows/deploy-pricing-service.yml | 6 +- .../deploy-product-management-service.yml | 6 +- .github/workflows/deploy-shared-services.yml | 8 +- .../deploy-user-management-service.yml | 8 +- src/pricing-service/package-lock.json | 14670 ++-------------- src/pricing-service/package.json | 2 +- 11 files changed, 1322 insertions(+), 13406 deletions(-) diff --git a/.github/workflows/deploy-activity-service.yml b/.github/workflows/deploy-activity-service.yml index 81a2801b..30b69d3e 100644 --- a/.github/workflows/deploy-activity-service.yml +++ b/.github/workflows/deploy-activity-service.yml @@ -31,7 +31,7 @@ jobs: # python-version: "3.13" # cache: "poetry" # NOTE: poetry must be installed before this step, or else cache doesn't work # - name: Configure AWS credentials - # uses: aws-actions/configure-aws-credentials@master + # uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # with: # role-to-assume: ${{ secrets.AWS_ROLE_ARN }} # role-session-name: GitHub_to_AWS_via_FederatedOIDC @@ -262,7 +262,7 @@ jobs: cache: "poetry" # NOTE: poetry must be installed before this step, or else cache doesn't work - uses: aws-actions/setup-sam@v1 - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC diff --git a/.github/workflows/deploy-build-image.yml b/.github/workflows/deploy-build-image.yml index d9b04429..b679354f 100644 --- a/.github/workflows/deploy-build-image.yml +++ b/.github/workflows/deploy-build-image.yml @@ -21,7 +21,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC diff --git a/.github/workflows/deploy-inventory-service.yml b/.github/workflows/deploy-inventory-service.yml index 250d7df7..348a3f6a 100644 --- a/.github/workflows/deploy-inventory-service.yml +++ b/.github/workflows/deploy-inventory-service.yml @@ -30,7 +30,7 @@ jobs: distribution: "corretto" architecture: x64 - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC @@ -84,7 +84,7 @@ jobs: distribution: "corretto" architecture: x64 - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC @@ -207,7 +207,7 @@ jobs: distribution: "corretto" architecture: x64 - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC @@ -316,7 +316,7 @@ jobs: architecture: x64 - uses: aws-actions/setup-sam@v1 - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC diff --git a/.github/workflows/deploy-loyalty-service.yml b/.github/workflows/deploy-loyalty-service.yml index 75ea548b..ed2633e2 100644 --- a/.github/workflows/deploy-loyalty-service.yml +++ b/.github/workflows/deploy-loyalty-service.yml @@ -32,7 +32,7 @@ jobs: with: node-version: "22" - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC @@ -136,7 +136,7 @@ jobs: run: | npm install -g aws-cdk - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC @@ -230,7 +230,7 @@ jobs: node-version: "22" - uses: aws-actions/setup-sam@v1 - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC diff --git a/.github/workflows/deploy-orders-service.yml b/.github/workflows/deploy-orders-service.yml index a26d70ad..daccb9f7 100644 --- a/.github/workflows/deploy-orders-service.yml +++ b/.github/workflows/deploy-orders-service.yml @@ -30,7 +30,7 @@ jobs: with: dotnet-version: "9.0.x" - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC @@ -83,7 +83,7 @@ jobs: with: dotnet-version: "9.0.x" - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC @@ -203,7 +203,7 @@ jobs: with: dotnet-version: "9.0.x" - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC @@ -297,7 +297,7 @@ jobs: dotnet-version: "9.0.x" - uses: aws-actions/setup-sam@v1 - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC diff --git a/.github/workflows/deploy-pricing-service.yml b/.github/workflows/deploy-pricing-service.yml index 4969ce3e..c6ddd545 100644 --- a/.github/workflows/deploy-pricing-service.yml +++ b/.github/workflows/deploy-pricing-service.yml @@ -32,7 +32,7 @@ jobs: with: node-version: "22" - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC @@ -136,7 +136,7 @@ jobs: run: | npm install -g aws-cdk - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC @@ -230,7 +230,7 @@ jobs: node-version: "22" - uses: aws-actions/setup-sam@v1 - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC diff --git a/.github/workflows/deploy-product-management-service.yml b/.github/workflows/deploy-product-management-service.yml index 5e0a0524..69634156 100644 --- a/.github/workflows/deploy-product-management-service.yml +++ b/.github/workflows/deploy-product-management-service.yml @@ -29,7 +29,7 @@ jobs: uses: hashicorp/setup-terraform@v2 - uses: actions/setup-go@v5 - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC @@ -141,7 +141,7 @@ jobs: run: | npm install -g aws-cdk - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC @@ -225,7 +225,7 @@ jobs: - uses: actions/setup-go@v5 - uses: aws-actions/setup-sam@v1 - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC diff --git a/.github/workflows/deploy-shared-services.yml b/.github/workflows/deploy-shared-services.yml index d69309a2..e00ba398 100644 --- a/.github/workflows/deploy-shared-services.yml +++ b/.github/workflows/deploy-shared-services.yml @@ -28,7 +28,7 @@ jobs: - name: Setup Terraform uses: hashicorp/setup-terraform@v2 - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC @@ -65,7 +65,7 @@ jobs: run: | npm install -g aws-cdk - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC @@ -99,7 +99,7 @@ jobs: node-version: "22" - uses: aws-actions/setup-sam@v1 - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC @@ -130,7 +130,7 @@ jobs: with: node-version: "22" - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC diff --git a/.github/workflows/deploy-user-management-service.yml b/.github/workflows/deploy-user-management-service.yml index c81408c6..1cc29b20 100644 --- a/.github/workflows/deploy-user-management-service.yml +++ b/.github/workflows/deploy-user-management-service.yml @@ -33,7 +33,7 @@ jobs: run: | cargo install cargo-lambda - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC @@ -145,7 +145,7 @@ jobs: run: | cargo install cargo-lambda - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC @@ -237,7 +237,7 @@ jobs: cargo install cargo-lambda - uses: aws-actions/setup-sam@v1 - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@master + uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} role-session-name: GitHub_to_AWS_via_FederatedOIDC @@ -327,7 +327,7 @@ jobs: # run: | # cargo install cargo-lambda # - name: Configure AWS credentials - # uses: aws-actions/configure-aws-credentials@master + # uses: aws-actions/configure-aws-credentials@b47578312673ae6fa5b5096b330d9fbac3d116df # with: # role-to-assume: ${{ secrets.AWS_ROLE_ARN }} # role-session-name: GitHub_to_AWS_via_FederatedOIDC diff --git a/src/pricing-service/package-lock.json b/src/pricing-service/package-lock.json index c27d0d3c..78ecd2bb 100644 --- a/src/pricing-service/package-lock.json +++ b/src/pricing-service/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "@aws-lambda-powertools/logger": "^2.20.0", "@aws-lambda-powertools/parameters": "^2.20.0", - "@types/jsonwebtoken": "^9.0.9", + "@types/jsonwebtoken": "^9.0.10", "cloudevents": "^9.0.0", "jsonwebtoken": "^9.0.2", "zod": "^3.25.49" @@ -19074,9 +19074,9 @@ "dev": true }, "node_modules/@types/jsonwebtoken": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.9.tgz", - "integrity": "sha512-uoe+GxEuHbvy12OUQct2X9JenKM3qAscquYymuQN4fMWG9DBQtykrQEFcAbVACF7qaLw9BePSodUL0kquqBJpQ==", + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz", + "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==", "dependencies": { "@types/ms": "*", "@types/node": "*" @@ -21282,41 +21282,6 @@ "docker-credential-cdk-assets": "bin/docker-credential-cdk-assets" } }, - "node_modules/cdk-assets/node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@asamuzakjp/css-color": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-2.8.3.tgz", - "integrity": "sha512-GIc76d9UI1hCvOATjZPyHFmE5qhRccp3/zGfMPapK3jBi+yocEzp6BBB0UnfRYP9NP4FANqUZYb0hnfs3TM3hw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@csstools/css-calc": "^2.1.1", - "@csstools/css-color-parser": "^3.0.7", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "lru-cache": "^10.4.3" - } - }, - "node_modules/cdk-assets/node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "extraneous": true, - "license": "ISC" - }, "node_modules/cdk-assets/node_modules/@aws-cdk/cloud-assembly-schema": { "version": "39.2.15", "resolved": "https://registry.npmjs.org/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-39.2.15.tgz", @@ -22883,13670 +22848,1750 @@ "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/abort-controller": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.1.tgz", + "integrity": "sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/compat-data": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.5.tgz", - "integrity": "sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/chunked-blob-reader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-5.0.0.tgz", + "integrity": "sha512-+sKqDBQqb036hh4NPaUiEkYFkTUGYzRsn3EuFhyfQfMy6oGHEUJDurLP9Ufb5dasr/XiAmPNMr6wa9afjQB+Gw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/core": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.7.tgz", - "integrity": "sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/chunked-blob-reader-native": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-4.0.0.tgz", + "integrity": "sha512-R9wM2yPmfEMsUmlMlIgSzOyICs0x9uu7UTHoccMyt7BWw8shcGM8HqB355+BZCPBcySvbTYMs62EgEQkNxz2ig==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.5", - "@babel/helper-compilation-targets": "^7.26.5", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.7", - "@babel/parser": "^7.26.7", - "@babel/template": "^7.25.9", - "@babel/traverse": "^7.26.7", - "@babel/types": "^7.26.7", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" + "@smithy/util-base64": "^4.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "extraneous": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/cdk-assets/node_modules/@smithy/config-resolver": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.13.tgz", + "integrity": "sha512-Gr/qwzyPaTL1tZcq8WQyHhTZREER5R1Wytmz4WnVGL4onA3dNk6Btll55c8Vr58pLdvWZmtG8oZxJTw3t3q7Jg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/node-config-provider": "^3.1.12", + "@smithy/types": "^3.7.2", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.11", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/generator": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.5.tgz", - "integrity": "sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/config-resolver/node_modules/@smithy/types": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.7.2.tgz", + "integrity": "sha512-bNwBYYmN8Eh9RyjS1p2gW6MIhSO2rl7X9QeLM8iTdcGRP+eDiIWDt66c9IysCc22gefKszZv+ubV9qZc7hdESg==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/parser": "^7.26.5", - "@babel/types": "^7.26.5", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/helper-compilation-targets": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", - "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/config-resolver/node_modules/@smithy/util-config-provider": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", + "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/compat-data": "^7.26.5", - "@babel/helper-validator-option": "^7.25.9", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "extraneous": true, - "license": "ISC", + "node_modules/cdk-assets/node_modules/@smithy/config-resolver/node_modules/@smithy/util-middleware": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.11.tgz", + "integrity": "sha512-dWpyc1e1R6VoXrwLoLDd57U1z6CwNSdkM69Ie4+6uYh2GC7Vg51Qtan7ITzczuVpqezdDTKJGJB95fFvvjU/ow==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "yallist": "^3.0.2" + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "extraneous": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/cdk-assets/node_modules/@smithy/core": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.1.2.tgz", + "integrity": "sha512-htwQXkbdF13uwwDevz9BEzL5ABK+1sJpVQXywwGSH973AVOvisHNfpcB8A8761G6XgHoS2kHPqc9DqHJ2gp+/Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/middleware-serde": "^4.0.2", + "@smithy/protocol-http": "^5.0.1", + "@smithy/types": "^4.1.0", + "@smithy/util-body-length-browser": "^4.0.0", + "@smithy/util-middleware": "^4.0.1", + "@smithy/util-stream": "^4.0.2", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/helper-compilation-targets/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "extraneous": true, - "license": "ISC" - }, - "node_modules/cdk-assets/node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/credential-provider-imds": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.0.1.tgz", + "integrity": "sha512-l/qdInaDq1Zpznpmev/+52QomsJNZ3JkTl5yrTl02V6NBgJOQ4LY0SFw/8zsMwj3tLe8vqiIuwF6nxaEwgf6mg==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@smithy/node-config-provider": "^4.0.1", + "@smithy/property-provider": "^4.0.1", + "@smithy/types": "^4.1.0", + "@smithy/url-parser": "^4.0.1", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/credential-provider-imds/node_modules/@smithy/node-config-provider": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.0.1.tgz", + "integrity": "sha512-8mRTjvCtVET8+rxvmzRNRR0hH2JjV0DFOmwXPrISmTIJEfnCBugpYYGAsCj8t41qd+RB5gbheSQ/6aKZCQvFLQ==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/helper-plugin-utils": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", - "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/eventstream-codec": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.0.1.tgz", + "integrity": "sha512-Q2bCAAR6zXNVtJgifsU16ZjKGqdw/DyecKNgIgi7dlqw04fqDu0mnq+JmGphqheypVc64CYq3azSuCpAdFk2+A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/crc32": "5.2.0", + "@smithy/types": "^4.1.0", + "@smithy/util-hex-encoding": "^4.0.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/eventstream-serde-browser": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.0.1.tgz", + "integrity": "sha512-HbIybmz5rhNg+zxKiyVAnvdM3vkzjE6ccrJ620iPL8IXcJEntd3hnBl+ktMwIy12Te/kyrSbUb8UCdnUT4QEdA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/eventstream-serde-universal": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/cdk-assets/node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/cdk-assets/node_modules/@babel/helpers": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.7.tgz", - "integrity": "sha512-8NHiL98vsi0mbPQmYAGWwfcFaOy4j2HY49fXJCfuDcdE7fMIsH9a7GdaeXpIBsbT7307WU8KCMp5pUVDNL4f9A==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/eventstream-serde-config-resolver": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.0.1.tgz", + "integrity": "sha512-lSipaiq3rmHguHa3QFF4YcCM3VJOrY9oq2sow3qlhFY+nBSTF/nrO82MUQRPrxHQXA58J5G1UnU2WuJfi465BA==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/template": "^7.25.9", - "@babel/types": "^7.26.7" + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/parser": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.7.tgz", - "integrity": "sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/eventstream-serde-node": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.0.1.tgz", + "integrity": "sha512-o4CoOI6oYGYJ4zXo34U8X9szDe3oGjmHgsMGiZM0j4vtNoT+h80TLnkUcrLZR3+E6HIxqW+G+9WHAVfl0GXK0Q==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/types": "^7.26.7" - }, - "bin": { - "parser": "bin/babel-parser.js" + "@smithy/eventstream-serde-universal": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.0.0" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/eventstream-serde-universal": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.0.1.tgz", + "integrity": "sha512-Z94uZp0tGJuxds3iEAZBqGU2QiaBHP4YytLUjwZWx+oUeohCsLyUm33yp4MMBmhkuPqSbQCXq5hDet6JGUgHWA==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@smithy/eventstream-codec": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/fetch-http-handler": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.0.1.tgz", + "integrity": "sha512-3aS+fP28urrMW2KTjb6z9iFow6jO8n3MFfineGbndvzGZit3taZhKWtTorf+Gp5RpFDDafeHlhfsGlDCXvUnJA==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@smithy/protocol-http": "^5.0.1", + "@smithy/querystring-builder": "^4.0.1", + "@smithy/types": "^4.1.0", + "@smithy/util-base64": "^4.0.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/hash-blob-browser": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.0.1.tgz", + "integrity": "sha512-rkFIrQOKZGS6i1D3gKJ8skJ0RlXqDvb1IyAphksaFOMzkn3v3I1eJ8m7OkLj0jf1McP63rcCEoLlkAn/HjcTRw==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" + "@smithy/chunked-blob-reader": "^5.0.0", + "@smithy/chunked-blob-reader-native": "^4.0.0", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/hash-node": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.0.1.tgz", + "integrity": "sha512-TJ6oZS+3r2Xu4emVse1YPB3Dq3d8RkZDKcPr71Nj/lJsdAP1c7oFzYqEn1IBc915TsgLl2xIJNuxCz+gLbLE0w==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@smithy/types": "^4.1.0", + "@smithy/util-buffer-from": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", - "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/hash-stream-node": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.0.1.tgz", + "integrity": "sha512-U1rAE1fxmReCIr6D2o/4ROqAQX+GffZpyMt3d7njtGDr2pUNmAKRWa49gsNVhCh2vVAuf3wXzWwNr2YN8PAXIw==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@smithy/types": "^4.1.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/invalid-dependency": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.0.1.tgz", + "integrity": "sha512-gdudFPf4QRQ5pzj7HEnu6FhKRi61BfH/Gk5Yf6O0KiSbr1LlVhgjThcvjdu658VE6Nve8vaIWB8/fodmS1rBPQ==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/is-array-buffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.0.0.tgz", + "integrity": "sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/plugin-syntax-jsx": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", - "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/md5-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.0.1.tgz", + "integrity": "sha512-HLZ647L27APi6zXkZlzSFZIjpo8po45YiyjMGJZM3gyDY8n7dPGdmxIIljLm4gPt/7rRvutLTTkYJpZVfG5r+A==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@smithy/types": "^4.1.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/middleware-content-length": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.0.1.tgz", + "integrity": "sha512-OGXo7w5EkB5pPiac7KNzVtfCW2vKBTZNuCctn++TTSOMpe6RZO/n6WEC1AxJINn3+vWLKW49uad3lo/u0WJ9oQ==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@smithy/protocol-http": "^5.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/middleware-endpoint": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.0.3.tgz", + "integrity": "sha512-YdbmWhQF5kIxZjWqPIgboVfi8i5XgiYMM7GGKFMTvBei4XjNQfNv8sukT50ITvgnWKKKpOtp0C0h7qixLgb77Q==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@smithy/core": "^3.1.2", + "@smithy/middleware-serde": "^4.0.2", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "@smithy/url-parser": "^4.0.1", + "@smithy/util-middleware": "^4.0.1", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/middleware-endpoint/node_modules/@smithy/node-config-provider": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.0.1.tgz", + "integrity": "sha512-8mRTjvCtVET8+rxvmzRNRR0hH2JjV0DFOmwXPrISmTIJEfnCBugpYYGAsCj8t41qd+RB5gbheSQ/6aKZCQvFLQ==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/middleware-retry": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.0.4.tgz", + "integrity": "sha512-wmxyUBGHaYUqul0wZiset4M39SMtDBOtUr2KpDuftKNN74Do9Y36Go6Eqzj9tL0mIPpr31ulB5UUtxcsCeGXsQ==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@smithy/node-config-provider": "^4.0.1", + "@smithy/protocol-http": "^5.0.1", + "@smithy/service-error-classification": "^4.0.1", + "@smithy/smithy-client": "^4.1.3", + "@smithy/types": "^4.1.0", + "@smithy/util-middleware": "^4.0.1", + "@smithy/util-retry": "^4.0.1", + "tslib": "^2.6.2", + "uuid": "^9.0.1" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/middleware-retry/node_modules/@smithy/node-config-provider": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.0.1.tgz", + "integrity": "sha512-8mRTjvCtVET8+rxvmzRNRR0hH2JjV0DFOmwXPrISmTIJEfnCBugpYYGAsCj8t41qd+RB5gbheSQ/6aKZCQvFLQ==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/middleware-serde": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.2.tgz", + "integrity": "sha512-Sdr5lOagCn5tt+zKsaW+U2/iwr6bI9p08wOkCp6/eL6iMbgdtc2R5Ety66rf87PeohR0ExI84Txz9GYv5ou3iQ==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/middleware-stack": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.0.1.tgz", + "integrity": "sha512-dHwDmrtR/ln8UTHpaIavRSzeIk5+YZTBtLnKwDW3G2t6nAupCiQUvNzNoHBpik63fwUaJPtlnMzXbQrNFWssIA==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/node-config-provider": { + "version": "3.1.12", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.12.tgz", + "integrity": "sha512-O9LVEu5J/u/FuNlZs+L7Ikn3lz7VB9hb0GtPT9MQeiBmtK8RSY3ULmsZgXhe6VAlgTw0YO+paQx4p8xdbs43vQ==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@smithy/property-provider": "^3.1.11", + "@smithy/shared-ini-file-loader": "^3.1.12", + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=16.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/plugin-syntax-typescript": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", - "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/node-config-provider/node_modules/@smithy/property-provider": { + "version": "3.1.11", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.11.tgz", + "integrity": "sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=16.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/template": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", - "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/node-config-provider/node_modules/@smithy/shared-ini-file-loader": { + "version": "3.1.12", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.12.tgz", + "integrity": "sha512-1xKSGI+U9KKdbG2qDvIR9dGrw3CNx+baqJfyr0igKEpjbHL5stsqAesYBzHChYHlelWtb87VnLWlhvfCz13H8Q==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/parser": "^7.25.9", - "@babel/types": "^7.25.9" + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/traverse": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.7.tgz", - "integrity": "sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/node-config-provider/node_modules/@smithy/types": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.7.2.tgz", + "integrity": "sha512-bNwBYYmN8Eh9RyjS1p2gW6MIhSO2rl7X9QeLM8iTdcGRP+eDiIWDt66c9IysCc22gefKszZv+ubV9qZc7hdESg==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.5", - "@babel/parser": "^7.26.7", - "@babel/template": "^7.25.9", - "@babel/types": "^7.26.7", - "debug": "^4.3.1", - "globals": "^11.1.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=16.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/node-http-handler": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.2.tgz", + "integrity": "sha512-X66H9aah9hisLLSnGuzRYba6vckuFtGE+a5DcHLliI/YlqKrGoxhisD5XbX44KyoeRzoNlGr94eTsMVHFAzPOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/abort-controller": "^4.0.1", + "@smithy/protocol-http": "^5.0.1", + "@smithy/querystring-builder": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=4" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@babel/types": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.7.tgz", - "integrity": "sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/property-provider": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.0.1.tgz", + "integrity": "sha512-o+VRiwC2cgmk/WFV0jaETGOtX16VNPp2bSQEzu0whbReqE1BMqsP2ami2Vi3cbGVdKu1kq9gQkDAGKbt0WOHAQ==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@cdklabs/eslint-plugin": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@cdklabs/eslint-plugin/-/eslint-plugin-1.3.2.tgz", - "integrity": "sha512-PWh8MOKgPOYRGRdd/eiPS93F4B/pahhHsNAtLderZ2XtaxfipE55AfSeiXRde2B4OUIYoIRh02b+On+3HZurTQ==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/@smithy/protocol-http": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.0.1.tgz", + "integrity": "sha512-TE4cpj49jJNB/oHyh/cRVEgNZaoPaxd4vteJNB0yGidOCVR0jCw/hjPVsT8Q8FRmj8Bd3bFZt8Dh7xGCT+xMBQ==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "fs-extra": "^11.3.0" + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">= 18.12.0" + "node": ">=18.0.0" + } + }, + "node_modules/cdk-assets/node_modules/@smithy/querystring-builder": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.1.tgz", + "integrity": "sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.1.0", + "@smithy/util-uri-escape": "^4.0.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.18.0", - "eslint": ">=6 <9" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@cdklabs/eslint-plugin/node_modules/fs-extra": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", - "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/querystring-parser": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.0.1.tgz", + "integrity": "sha512-Ma2XC7VS9aV77+clSFylVUnPZRindhB7BbmYiNOdr+CHt/kZNJoPP0cd3QxCnCFyPXC4eybmyE98phEHkqZ5Jw==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=14.14" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/service-error-classification": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.0.1.tgz", + "integrity": "sha512-3JNjBfOWpj/mYfjXJHB4Txc/7E4LVq32bwzE7m28GN79+M1f76XHflUaSUkhOriprPDzev9cX/M+dEB80DNDKA==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" + "@smithy/types": "^4.1.0" }, "engines": { - "node": ">=12" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/shared-ini-file-loader": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.1.tgz", + "integrity": "sha512-hC8F6qTBbuHRI/uqDgqqi6J0R4GtEZcgrZPhFQnMhfJs3MnUTGSnR1NSJCJs5VWlMydu0kJz15M640fJlRsIOw==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@csstools/color-helpers": { + "node_modules/cdk-assets/node_modules/@smithy/signature-v4": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.0.1.tgz", - "integrity": "sha512-MKtmkA0BX87PKaO1NFRTFH+UnkgnmySQOvNxJubsadusqPEC2aJ9MOQiMceZJJ6oitUl/i0L6u0M1IrmAOmgBA==", - "extraneous": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/@csstools/css-calc": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.1.tgz", - "integrity": "sha512-rL7kaUnTkL9K+Cvo2pnCieqNpTKgQzy5f+N+5Iuko9HAoasP+xgprVh7KN/MaJVvVL1l0EzQq2MoqBHKSrDrag==", - "extraneous": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "engines": { - "node": ">=18" + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.0.1.tgz", + "integrity": "sha512-nCe6fQ+ppm1bQuw5iKoeJ0MJfz2os7Ic3GBjOkLOPtavbD1ONoyE3ygjBfz2ythFWm4YnRm6OxW+8p/m9uCoIA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^4.0.0", + "@smithy/protocol-http": "^5.0.1", + "@smithy/types": "^4.1.0", + "@smithy/util-hex-encoding": "^4.0.0", + "@smithy/util-middleware": "^4.0.1", + "@smithy/util-uri-escape": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@csstools/css-color-parser": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.0.7.tgz", - "integrity": "sha512-nkMp2mTICw32uE5NN+EsJ4f5N+IGFeCFu4bGpiKgb2Pq/7J/MpyLBeQ5ry4KKtRFZaYs6sTmcMYrSRIyj5DFKA==", - "extraneous": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/smithy-client": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.1.3.tgz", + "integrity": "sha512-A2Hz85pu8BJJaYFdX8yb1yocqigyqBzn+OVaVgm+Kwi/DkN8vhN2kbDVEfADo6jXf5hPKquMLGA3UINA64UZ7A==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@csstools/color-helpers": "^5.0.1", - "@csstools/css-calc": "^2.1.1" + "@smithy/core": "^3.1.2", + "@smithy/middleware-endpoint": "^4.0.3", + "@smithy/middleware-stack": "^4.0.1", + "@smithy/protocol-http": "^5.0.1", + "@smithy/types": "^4.1.0", + "@smithy/util-stream": "^4.0.2", + "tslib": "^2.6.2" }, "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@csstools/css-parser-algorithms": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz", - "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==", - "extraneous": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "engines": { - "node": ">=18" + "node_modules/cdk-assets/node_modules/@smithy/types": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", + "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" }, - "peerDependencies": { - "@csstools/css-tokenizer": "^3.0.3" - } - }, - "node_modules/cdk-assets/node_modules/@csstools/css-tokenizer": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz", - "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==", - "extraneous": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", "engines": { - "node": ">=18" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@dependents/detective-less": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@dependents/detective-less/-/detective-less-5.0.1.tgz", - "integrity": "sha512-Y6+WUMsTFWE5jb20IFP4YGa5IrGY/+a/FbOSjDF/wz9gepU2hwCYSXRHP/vPwBvwcY3SVMASt4yXxbXNXigmZQ==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/url-parser": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.1.tgz", + "integrity": "sha512-gPXcIEUtw7VlK8f/QcruNXm7q+T5hhvGu9tl63LsJPZ27exB6dtNwvh2HIi0v7JcXJ5emBxB+CJxwaLEdJfA+g==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "gonzales-pe": "^4.3.0", - "node-source-walk": "^7.0.1" + "@smithy/querystring-parser": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=18" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/util-base64": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.0.0.tgz", + "integrity": "sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "eslint-visitor-keys": "^3.4.3" + "@smithy/util-buffer-from": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/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==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/@smithy/util-body-length-browser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.0.0.tgz", + "integrity": "sha512-sNi3DL0/k64/LO3A256M+m3CDdG6V7WKWHdAiBBMUN8S3hK3aMPhwnPik2A/a2ONN+9doY9UxaLfgqsIRg69QA==", + "dev": true, "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "dependencies": { + "tslib": "^2.6.2" }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@eslint/config-array": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz", - "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/@smithy/util-body-length-node": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.0.0.tgz", + "integrity": "sha512-q0iDP3VsZzqJyje8xJWEJCNIu3lktUGVoSy1KB0UWym2CL1siV3artm+u1DFYTLejpsrdGyCSWBdGNjJzfDPjg==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.6", - "debug": "^4.3.1", - "minimatch": "^3.1.2" + "tslib": "^2.6.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/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==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/@smithy/util-buffer-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.0.0.tgz", + "integrity": "sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@types/json-schema": "^7.0.15" + "@smithy/is-array-buffer": "^4.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/util-config-provider": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.0.0.tgz", + "integrity": "sha512-L1RBVzLyfE8OXH+1hsJ8p+acNUSirQnWQ6/EgpchV88G6zGBTDPdXiiExei6Z1wR2RxYvxY/XLw6AMNCCt8H3w==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "tslib": "^2.6.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@eslint/eslintrc/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==", - "extraneous": true, - "license": "Python-2.0" - }, - "node_modules/cdk-assets/node_modules/@eslint/eslintrc/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==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/@smithy/util-defaults-mode-browser": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.4.tgz", + "integrity": "sha512-Ej1bV5sbrIfH++KnWxjjzFNq9nyP3RIUq2c9Iqq7SmMO/idUR24sqvKH2LUQFTSPy/K7G4sB2m8n7YYlEAfZaw==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "argparse": "^2.0.1" + "@smithy/property-provider": "^4.0.1", + "@smithy/smithy-client": "^4.1.3", + "@smithy/types": "^4.1.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/@smithy/util-defaults-mode-node": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.4.tgz", + "integrity": "sha512-HE1I7gxa6yP7ZgXPCFfZSDmVmMtY7SHqzFF55gM/GPegzZKaQWZZ+nYn9C2Cc3JltCMyWe63VPR3tSFDEvuGjw==", + "dev": true, "license": "Apache-2.0", + "dependencies": { + "@smithy/config-resolver": "^4.0.1", + "@smithy/credential-provider-imds": "^4.0.1", + "@smithy/node-config-provider": "^4.0.1", + "@smithy/property-provider": "^4.0.1", + "@smithy/smithy-client": "^4.1.3", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/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==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/@smithy/util-defaults-mode-node/node_modules/@smithy/config-resolver": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.0.1.tgz", + "integrity": "sha512-Igfg8lKu3dRVkTSEm98QpZUvKEOa71jDX4vKRcvJVyRc3UgN3j7vFMf0s7xLQhYmKa8kyJGQgUJDOV5V3neVlQ==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.10.0", - "levn": "^0.4.1" + "@smithy/node-config-provider": "^4.0.1", + "@smithy/types": "^4.1.0", + "@smithy/util-config-provider": "^4.0.0", + "@smithy/util-middleware": "^4.0.1", + "tslib": "^2.6.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/@smithy/util-defaults-mode-node/node_modules/@smithy/node-config-provider": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.0.1.tgz", + "integrity": "sha512-8mRTjvCtVET8+rxvmzRNRR0hH2JjV0DFOmwXPrISmTIJEfnCBugpYYGAsCj8t41qd+RB5gbheSQ/6aKZCQvFLQ==", + "dev": true, "license": "Apache-2.0", + "dependencies": { + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=18.18.0" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@humanfs/node": { - "version": "0.16.6", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", - "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/@smithy/util-endpoints": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.0.1.tgz", + "integrity": "sha512-zVdUENQpdtn9jbpD9SCFK4+aSiavRb9BxEtw9ZGUR1TYo6bBHbIoi7VkrFQ0/RwZlzx0wRBaRmPclj8iAoJCLA==", + "dev": true, "license": "Apache-2.0", "dependencies": { - "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.3.0" + "@smithy/node-config-provider": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=18.18.0" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", - "extraneous": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "node_modules/cdk-assets/node_modules/@smithy/util-endpoints/node_modules/@smithy/node-config-provider": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.0.1.tgz", + "integrity": "sha512-8mRTjvCtVET8+rxvmzRNRR0hH2JjV0DFOmwXPrISmTIJEfnCBugpYYGAsCj8t41qd+RB5gbheSQ/6aKZCQvFLQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/property-provider": "^4.0.1", + "@smithy/shared-ini-file-loader": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/@smithy/util-hex-encoding": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.0.0.tgz", + "integrity": "sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==", + "dev": true, "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, "engines": { - "node": ">=12.22" + "node": ">=18.0.0" + } + }, + "node_modules/cdk-assets/node_modules/@smithy/util-middleware": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.1.tgz", + "integrity": "sha512-HiLAvlcqhbzhuiOa0Lyct5IIlyIz0PQO5dnMlmQ/ubYM46dPInB+3yQGkfxsk6Q24Y0n3/JmcA1v5iEhmOF5mA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/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==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/@smithy/util-retry": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.1.tgz", + "integrity": "sha512-WmRHqNVwn3kI3rKk1LsKcVgPBG6iLTBGC1iYOV3GQegwJ3E8yjzHytPt26VNzOWr1qu0xE03nK0Ug8S7T7oufw==", + "dev": true, "license": "Apache-2.0", + "dependencies": { + "@smithy/service-error-classification": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=18.18" + "node": ">=18.0.0" + } + }, + "node_modules/cdk-assets/node_modules/@smithy/util-stream": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.0.2.tgz", + "integrity": "sha512-0eZ4G5fRzIoewtHtwaYyl8g2C+osYOT4KClXgfdNEDAgkbe2TYPqcnw4GAWabqkZCax2ihRGPe9LZnsPdIUIHA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/fetch-http-handler": "^5.0.1", + "@smithy/node-http-handler": "^4.0.2", + "@smithy/types": "^4.1.0", + "@smithy/util-base64": "^4.0.0", + "@smithy/util-buffer-from": "^4.0.0", + "@smithy/util-hex-encoding": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@hutson/parse-repository-url": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", - "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/@smithy/util-uri-escape": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz", + "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==", + "dev": true, "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@iarna/toml": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", - "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", - "extraneous": true, - "license": "ISC" + "node_modules/cdk-assets/node_modules/@smithy/util-utf8": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.0.0.tgz", + "integrity": "sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } }, - "node_modules/cdk-assets/node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "extraneous": true, - "license": "ISC", + "node_modules/cdk-assets/node_modules/@smithy/util-waiter": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.0.2.tgz", + "integrity": "sha512-piUTHyp2Axx3p/kc2CIJkYSv0BAaheBQmbACZgQSSfWUumWNW+R1lL+H9PDBxKJkvOeEX+hKYEFiwO8xagL8AQ==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" + "@smithy/abort-controller": "^4.0.1", + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=8" + "node": ">=18.0.0" } }, - "node_modules/cdk-assets/node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true, + "license": "MIT" + }, + "node_modules/cdk-assets/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/cdk-assets/node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/cdk-assets/node_modules/@jest/console/node_modules/@types/node": { - "version": "22.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", - "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/archiver": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", + "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", + "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "archiver-utils": "^2.1.0", + "async": "^3.2.4", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "engines": { + "node": ">= 10" } }, - "node_modules/cdk-assets/node_modules/@jest/console/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "node": ">= 6" } }, - "node_modules/cdk-assets/node_modules/@jest/core/node_modules/@types/node": { - "version": "22.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", - "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/archiver-utils/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cdk-assets/node_modules/archiver-utils/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/cdk-assets/node_modules/@jest/core/node_modules/jest-config": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/cdk-assets/node_modules/@jest/core/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@jest/environment/node_modules/@types/node": { - "version": "22.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", - "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/cdk-assets/node_modules/@jest/environment/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "jest-get-type": "^29.6.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@jest/fake-timers/node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "extraneous": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@jest/fake-timers/node_modules/@types/node": { - "version": "22.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", - "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/cdk-assets/node_modules/@jest/fake-timers/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/cdk-assets/node_modules/@jest/reporters/node_modules/@types/node": { - "version": "22.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", - "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/cdk-assets/node_modules/@jest/reporters/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@jest/types/node_modules/@types/node": { - "version": "22.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", - "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/cdk-assets/node_modules/@jest/types/node_modules/@types/yargs": { - "version": "17.0.33", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", - "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/cdk-assets/node_modules/@jest/types/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/cdk-assets/node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cdk-assets/node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/cdk-assets/node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cdk-assets/node_modules/@nolyfill/is-core-module": { - "version": "1.0.39", - "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", - "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=12.4.0" - } - }, - "node_modules/cdk-assets/node_modules/@oozcitak/dom": { - "version": "1.15.10", - "resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-1.15.10.tgz", - "integrity": "sha512-0JT29/LaxVgRcGKvHmSrUTEvZ8BXvZhGl2LASRUgHqDTC1M5g1pLmVv56IYNyt3bG2CUjDkc67wnyZC14pbQrQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@oozcitak/infra": "1.0.8", - "@oozcitak/url": "1.0.4", - "@oozcitak/util": "8.3.8" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/cdk-assets/node_modules/@oozcitak/infra": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-1.0.8.tgz", - "integrity": "sha512-JRAUc9VR6IGHOL7OGF+yrvs0LO8SlqGnPAMqyzOuFZPSZSXI7Xf2O9+awQPSMXgIWGtgUf/dA6Hs6X6ySEaWTg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@oozcitak/util": "8.3.8" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/cdk-assets/node_modules/@oozcitak/url": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@oozcitak/url/-/url-1.0.4.tgz", - "integrity": "sha512-kDcD8y+y3FCSOvnBI6HJgl00viO/nGbQoCINmQ0h98OhnGITrWR3bOGfwYCthgcrV8AnTJz8MzslTQbC3SOAmw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@oozcitak/infra": "1.0.8", - "@oozcitak/util": "8.3.8" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/cdk-assets/node_modules/@oozcitak/util": { - "version": "8.3.8", - "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-8.3.8.tgz", - "integrity": "sha512-T8TbSnGsxo6TDBJx/Sgv/BlVJL3tshxZP7Aq5R1mSnM5OcHY2dQaxLMu2+E8u3gN0MLOzdjurqN4ZRVuzQycOQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8.0" - } - }, - "node_modules/cdk-assets/node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/cdk-assets/node_modules/@rtsao/scc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", - "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "extraneous": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/cdk-assets/node_modules/@sinonjs/fake-timers": { - "version": "11.2.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", - "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", - "extraneous": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@sinonjs/samsam": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.2.tgz", - "integrity": "sha512-v46t/fwnhejRSFTGqbpn9u+LQ9xJDse10gNnPgAcxgdoCDMXj/G2asWAC/8Qs+BAZDicX+MNZouXT1A7c83kVw==", - "extraneous": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1", - "lodash.get": "^4.4.2", - "type-detect": "^4.1.0" - } - }, - "node_modules/cdk-assets/node_modules/@sinonjs/samsam/node_modules/type-detect": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", - "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/@sinonjs/text-encoding": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", - "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", - "extraneous": true, - "license": "(Unlicense OR Apache-2.0)" - }, - "node_modules/cdk-assets/node_modules/@smithy/abort-controller": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.1.tgz", - "integrity": "sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/chunked-blob-reader": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-5.0.0.tgz", - "integrity": "sha512-+sKqDBQqb036hh4NPaUiEkYFkTUGYzRsn3EuFhyfQfMy6oGHEUJDurLP9Ufb5dasr/XiAmPNMr6wa9afjQB+Gw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/chunked-blob-reader-native": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-4.0.0.tgz", - "integrity": "sha512-R9wM2yPmfEMsUmlMlIgSzOyICs0x9uu7UTHoccMyt7BWw8shcGM8HqB355+BZCPBcySvbTYMs62EgEQkNxz2ig==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-base64": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/config-resolver": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.13.tgz", - "integrity": "sha512-Gr/qwzyPaTL1tZcq8WQyHhTZREER5R1Wytmz4WnVGL4onA3dNk6Btll55c8Vr58pLdvWZmtG8oZxJTw3t3q7Jg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^3.1.12", - "@smithy/types": "^3.7.2", - "@smithy/util-config-provider": "^3.0.0", - "@smithy/util-middleware": "^3.0.11", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/config-resolver/node_modules/@smithy/types": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.7.2.tgz", - "integrity": "sha512-bNwBYYmN8Eh9RyjS1p2gW6MIhSO2rl7X9QeLM8iTdcGRP+eDiIWDt66c9IysCc22gefKszZv+ubV9qZc7hdESg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/config-resolver/node_modules/@smithy/util-config-provider": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", - "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/config-resolver/node_modules/@smithy/util-middleware": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.11.tgz", - "integrity": "sha512-dWpyc1e1R6VoXrwLoLDd57U1z6CwNSdkM69Ie4+6uYh2GC7Vg51Qtan7ITzczuVpqezdDTKJGJB95fFvvjU/ow==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^3.7.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/core": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.1.2.tgz", - "integrity": "sha512-htwQXkbdF13uwwDevz9BEzL5ABK+1sJpVQXywwGSH973AVOvisHNfpcB8A8761G6XgHoS2kHPqc9DqHJ2gp+/Q==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/middleware-serde": "^4.0.2", - "@smithy/protocol-http": "^5.0.1", - "@smithy/types": "^4.1.0", - "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-middleware": "^4.0.1", - "@smithy/util-stream": "^4.0.2", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/credential-provider-imds": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.0.1.tgz", - "integrity": "sha512-l/qdInaDq1Zpznpmev/+52QomsJNZ3JkTl5yrTl02V6NBgJOQ4LY0SFw/8zsMwj3tLe8vqiIuwF6nxaEwgf6mg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.0.1", - "@smithy/property-provider": "^4.0.1", - "@smithy/types": "^4.1.0", - "@smithy/url-parser": "^4.0.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/credential-provider-imds/node_modules/@smithy/node-config-provider": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.0.1.tgz", - "integrity": "sha512-8mRTjvCtVET8+rxvmzRNRR0hH2JjV0DFOmwXPrISmTIJEfnCBugpYYGAsCj8t41qd+RB5gbheSQ/6aKZCQvFLQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/property-provider": "^4.0.1", - "@smithy/shared-ini-file-loader": "^4.0.1", - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/eventstream-codec": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.0.1.tgz", - "integrity": "sha512-Q2bCAAR6zXNVtJgifsU16ZjKGqdw/DyecKNgIgi7dlqw04fqDu0mnq+JmGphqheypVc64CYq3azSuCpAdFk2+A==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/crc32": "5.2.0", - "@smithy/types": "^4.1.0", - "@smithy/util-hex-encoding": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/eventstream-serde-browser": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.0.1.tgz", - "integrity": "sha512-HbIybmz5rhNg+zxKiyVAnvdM3vkzjE6ccrJ620iPL8IXcJEntd3hnBl+ktMwIy12Te/kyrSbUb8UCdnUT4QEdA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/eventstream-serde-universal": "^4.0.1", - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/eventstream-serde-config-resolver": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.0.1.tgz", - "integrity": "sha512-lSipaiq3rmHguHa3QFF4YcCM3VJOrY9oq2sow3qlhFY+nBSTF/nrO82MUQRPrxHQXA58J5G1UnU2WuJfi465BA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/eventstream-serde-node": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.0.1.tgz", - "integrity": "sha512-o4CoOI6oYGYJ4zXo34U8X9szDe3oGjmHgsMGiZM0j4vtNoT+h80TLnkUcrLZR3+E6HIxqW+G+9WHAVfl0GXK0Q==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/eventstream-serde-universal": "^4.0.1", - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/eventstream-serde-universal": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.0.1.tgz", - "integrity": "sha512-Z94uZp0tGJuxds3iEAZBqGU2QiaBHP4YytLUjwZWx+oUeohCsLyUm33yp4MMBmhkuPqSbQCXq5hDet6JGUgHWA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/eventstream-codec": "^4.0.1", - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/fetch-http-handler": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.0.1.tgz", - "integrity": "sha512-3aS+fP28urrMW2KTjb6z9iFow6jO8n3MFfineGbndvzGZit3taZhKWtTorf+Gp5RpFDDafeHlhfsGlDCXvUnJA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/protocol-http": "^5.0.1", - "@smithy/querystring-builder": "^4.0.1", - "@smithy/types": "^4.1.0", - "@smithy/util-base64": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/hash-blob-browser": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.0.1.tgz", - "integrity": "sha512-rkFIrQOKZGS6i1D3gKJ8skJ0RlXqDvb1IyAphksaFOMzkn3v3I1eJ8m7OkLj0jf1McP63rcCEoLlkAn/HjcTRw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/chunked-blob-reader": "^5.0.0", - "@smithy/chunked-blob-reader-native": "^4.0.0", - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/hash-node": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.0.1.tgz", - "integrity": "sha512-TJ6oZS+3r2Xu4emVse1YPB3Dq3d8RkZDKcPr71Nj/lJsdAP1c7oFzYqEn1IBc915TsgLl2xIJNuxCz+gLbLE0w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.1.0", - "@smithy/util-buffer-from": "^4.0.0", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/hash-stream-node": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.0.1.tgz", - "integrity": "sha512-U1rAE1fxmReCIr6D2o/4ROqAQX+GffZpyMt3d7njtGDr2pUNmAKRWa49gsNVhCh2vVAuf3wXzWwNr2YN8PAXIw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.1.0", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/invalid-dependency": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.0.1.tgz", - "integrity": "sha512-gdudFPf4QRQ5pzj7HEnu6FhKRi61BfH/Gk5Yf6O0KiSbr1LlVhgjThcvjdu658VE6Nve8vaIWB8/fodmS1rBPQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/is-array-buffer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.0.0.tgz", - "integrity": "sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/md5-js": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.0.1.tgz", - "integrity": "sha512-HLZ647L27APi6zXkZlzSFZIjpo8po45YiyjMGJZM3gyDY8n7dPGdmxIIljLm4gPt/7rRvutLTTkYJpZVfG5r+A==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.1.0", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/middleware-content-length": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.0.1.tgz", - "integrity": "sha512-OGXo7w5EkB5pPiac7KNzVtfCW2vKBTZNuCctn++TTSOMpe6RZO/n6WEC1AxJINn3+vWLKW49uad3lo/u0WJ9oQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/protocol-http": "^5.0.1", - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/middleware-endpoint": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.0.3.tgz", - "integrity": "sha512-YdbmWhQF5kIxZjWqPIgboVfi8i5XgiYMM7GGKFMTvBei4XjNQfNv8sukT50ITvgnWKKKpOtp0C0h7qixLgb77Q==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.1.2", - "@smithy/middleware-serde": "^4.0.2", - "@smithy/node-config-provider": "^4.0.1", - "@smithy/shared-ini-file-loader": "^4.0.1", - "@smithy/types": "^4.1.0", - "@smithy/url-parser": "^4.0.1", - "@smithy/util-middleware": "^4.0.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/middleware-endpoint/node_modules/@smithy/node-config-provider": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.0.1.tgz", - "integrity": "sha512-8mRTjvCtVET8+rxvmzRNRR0hH2JjV0DFOmwXPrISmTIJEfnCBugpYYGAsCj8t41qd+RB5gbheSQ/6aKZCQvFLQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/property-provider": "^4.0.1", - "@smithy/shared-ini-file-loader": "^4.0.1", - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/middleware-retry": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.0.4.tgz", - "integrity": "sha512-wmxyUBGHaYUqul0wZiset4M39SMtDBOtUr2KpDuftKNN74Do9Y36Go6Eqzj9tL0mIPpr31ulB5UUtxcsCeGXsQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.0.1", - "@smithy/protocol-http": "^5.0.1", - "@smithy/service-error-classification": "^4.0.1", - "@smithy/smithy-client": "^4.1.3", - "@smithy/types": "^4.1.0", - "@smithy/util-middleware": "^4.0.1", - "@smithy/util-retry": "^4.0.1", - "tslib": "^2.6.2", - "uuid": "^9.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/middleware-retry/node_modules/@smithy/node-config-provider": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.0.1.tgz", - "integrity": "sha512-8mRTjvCtVET8+rxvmzRNRR0hH2JjV0DFOmwXPrISmTIJEfnCBugpYYGAsCj8t41qd+RB5gbheSQ/6aKZCQvFLQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/property-provider": "^4.0.1", - "@smithy/shared-ini-file-loader": "^4.0.1", - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/middleware-serde": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.2.tgz", - "integrity": "sha512-Sdr5lOagCn5tt+zKsaW+U2/iwr6bI9p08wOkCp6/eL6iMbgdtc2R5Ety66rf87PeohR0ExI84Txz9GYv5ou3iQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/middleware-stack": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.0.1.tgz", - "integrity": "sha512-dHwDmrtR/ln8UTHpaIavRSzeIk5+YZTBtLnKwDW3G2t6nAupCiQUvNzNoHBpik63fwUaJPtlnMzXbQrNFWssIA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/node-config-provider": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.12.tgz", - "integrity": "sha512-O9LVEu5J/u/FuNlZs+L7Ikn3lz7VB9hb0GtPT9MQeiBmtK8RSY3ULmsZgXhe6VAlgTw0YO+paQx4p8xdbs43vQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/property-provider": "^3.1.11", - "@smithy/shared-ini-file-loader": "^3.1.12", - "@smithy/types": "^3.7.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/node-config-provider/node_modules/@smithy/property-provider": { - "version": "3.1.11", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.11.tgz", - "integrity": "sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^3.7.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/node-config-provider/node_modules/@smithy/shared-ini-file-loader": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.12.tgz", - "integrity": "sha512-1xKSGI+U9KKdbG2qDvIR9dGrw3CNx+baqJfyr0igKEpjbHL5stsqAesYBzHChYHlelWtb87VnLWlhvfCz13H8Q==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^3.7.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/node-config-provider/node_modules/@smithy/types": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.7.2.tgz", - "integrity": "sha512-bNwBYYmN8Eh9RyjS1p2gW6MIhSO2rl7X9QeLM8iTdcGRP+eDiIWDt66c9IysCc22gefKszZv+ubV9qZc7hdESg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/node-http-handler": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.2.tgz", - "integrity": "sha512-X66H9aah9hisLLSnGuzRYba6vckuFtGE+a5DcHLliI/YlqKrGoxhisD5XbX44KyoeRzoNlGr94eTsMVHFAzPOw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/abort-controller": "^4.0.1", - "@smithy/protocol-http": "^5.0.1", - "@smithy/querystring-builder": "^4.0.1", - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/property-provider": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.0.1.tgz", - "integrity": "sha512-o+VRiwC2cgmk/WFV0jaETGOtX16VNPp2bSQEzu0whbReqE1BMqsP2ami2Vi3cbGVdKu1kq9gQkDAGKbt0WOHAQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/protocol-http": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.0.1.tgz", - "integrity": "sha512-TE4cpj49jJNB/oHyh/cRVEgNZaoPaxd4vteJNB0yGidOCVR0jCw/hjPVsT8Q8FRmj8Bd3bFZt8Dh7xGCT+xMBQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/querystring-builder": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.1.tgz", - "integrity": "sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.1.0", - "@smithy/util-uri-escape": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/querystring-parser": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.0.1.tgz", - "integrity": "sha512-Ma2XC7VS9aV77+clSFylVUnPZRindhB7BbmYiNOdr+CHt/kZNJoPP0cd3QxCnCFyPXC4eybmyE98phEHkqZ5Jw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/service-error-classification": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.0.1.tgz", - "integrity": "sha512-3JNjBfOWpj/mYfjXJHB4Txc/7E4LVq32bwzE7m28GN79+M1f76XHflUaSUkhOriprPDzev9cX/M+dEB80DNDKA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.1.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/shared-ini-file-loader": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.1.tgz", - "integrity": "sha512-hC8F6qTBbuHRI/uqDgqqi6J0R4GtEZcgrZPhFQnMhfJs3MnUTGSnR1NSJCJs5VWlMydu0kJz15M640fJlRsIOw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/signature-v4": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.0.1.tgz", - "integrity": "sha512-nCe6fQ+ppm1bQuw5iKoeJ0MJfz2os7Ic3GBjOkLOPtavbD1ONoyE3ygjBfz2ythFWm4YnRm6OxW+8p/m9uCoIA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/is-array-buffer": "^4.0.0", - "@smithy/protocol-http": "^5.0.1", - "@smithy/types": "^4.1.0", - "@smithy/util-hex-encoding": "^4.0.0", - "@smithy/util-middleware": "^4.0.1", - "@smithy/util-uri-escape": "^4.0.0", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/smithy-client": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.1.3.tgz", - "integrity": "sha512-A2Hz85pu8BJJaYFdX8yb1yocqigyqBzn+OVaVgm+Kwi/DkN8vhN2kbDVEfADo6jXf5hPKquMLGA3UINA64UZ7A==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.1.2", - "@smithy/middleware-endpoint": "^4.0.3", - "@smithy/middleware-stack": "^4.0.1", - "@smithy/protocol-http": "^5.0.1", - "@smithy/types": "^4.1.0", - "@smithy/util-stream": "^4.0.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/types": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", - "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/url-parser": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.1.tgz", - "integrity": "sha512-gPXcIEUtw7VlK8f/QcruNXm7q+T5hhvGu9tl63LsJPZ27exB6dtNwvh2HIi0v7JcXJ5emBxB+CJxwaLEdJfA+g==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/querystring-parser": "^4.0.1", - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/util-base64": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.0.0.tgz", - "integrity": "sha512-CvHfCmO2mchox9kjrtzoHkWHxjHZzaFojLc8quxXY7WAAMAg43nuxwv95tATVgQFNDwd4M9S1qFzj40Ul41Kmg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-buffer-from": "^4.0.0", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/util-body-length-browser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.0.0.tgz", - "integrity": "sha512-sNi3DL0/k64/LO3A256M+m3CDdG6V7WKWHdAiBBMUN8S3hK3aMPhwnPik2A/a2ONN+9doY9UxaLfgqsIRg69QA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/util-body-length-node": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.0.0.tgz", - "integrity": "sha512-q0iDP3VsZzqJyje8xJWEJCNIu3lktUGVoSy1KB0UWym2CL1siV3artm+u1DFYTLejpsrdGyCSWBdGNjJzfDPjg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/util-buffer-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.0.0.tgz", - "integrity": "sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/is-array-buffer": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/util-config-provider": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.0.0.tgz", - "integrity": "sha512-L1RBVzLyfE8OXH+1hsJ8p+acNUSirQnWQ6/EgpchV88G6zGBTDPdXiiExei6Z1wR2RxYvxY/XLw6AMNCCt8H3w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.4.tgz", - "integrity": "sha512-Ej1bV5sbrIfH++KnWxjjzFNq9nyP3RIUq2c9Iqq7SmMO/idUR24sqvKH2LUQFTSPy/K7G4sB2m8n7YYlEAfZaw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/property-provider": "^4.0.1", - "@smithy/smithy-client": "^4.1.3", - "@smithy/types": "^4.1.0", - "bowser": "^2.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/util-defaults-mode-node": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.4.tgz", - "integrity": "sha512-HE1I7gxa6yP7ZgXPCFfZSDmVmMtY7SHqzFF55gM/GPegzZKaQWZZ+nYn9C2Cc3JltCMyWe63VPR3tSFDEvuGjw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/config-resolver": "^4.0.1", - "@smithy/credential-provider-imds": "^4.0.1", - "@smithy/node-config-provider": "^4.0.1", - "@smithy/property-provider": "^4.0.1", - "@smithy/smithy-client": "^4.1.3", - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/util-defaults-mode-node/node_modules/@smithy/config-resolver": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.0.1.tgz", - "integrity": "sha512-Igfg8lKu3dRVkTSEm98QpZUvKEOa71jDX4vKRcvJVyRc3UgN3j7vFMf0s7xLQhYmKa8kyJGQgUJDOV5V3neVlQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.0.1", - "@smithy/types": "^4.1.0", - "@smithy/util-config-provider": "^4.0.0", - "@smithy/util-middleware": "^4.0.1", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/util-defaults-mode-node/node_modules/@smithy/node-config-provider": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.0.1.tgz", - "integrity": "sha512-8mRTjvCtVET8+rxvmzRNRR0hH2JjV0DFOmwXPrISmTIJEfnCBugpYYGAsCj8t41qd+RB5gbheSQ/6aKZCQvFLQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/property-provider": "^4.0.1", - "@smithy/shared-ini-file-loader": "^4.0.1", - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/util-endpoints": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.0.1.tgz", - "integrity": "sha512-zVdUENQpdtn9jbpD9SCFK4+aSiavRb9BxEtw9ZGUR1TYo6bBHbIoi7VkrFQ0/RwZlzx0wRBaRmPclj8iAoJCLA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/node-config-provider": "^4.0.1", - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/util-endpoints/node_modules/@smithy/node-config-provider": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.0.1.tgz", - "integrity": "sha512-8mRTjvCtVET8+rxvmzRNRR0hH2JjV0DFOmwXPrISmTIJEfnCBugpYYGAsCj8t41qd+RB5gbheSQ/6aKZCQvFLQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/property-provider": "^4.0.1", - "@smithy/shared-ini-file-loader": "^4.0.1", - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/util-hex-encoding": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.0.0.tgz", - "integrity": "sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/util-middleware": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.1.tgz", - "integrity": "sha512-HiLAvlcqhbzhuiOa0Lyct5IIlyIz0PQO5dnMlmQ/ubYM46dPInB+3yQGkfxsk6Q24Y0n3/JmcA1v5iEhmOF5mA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/util-retry": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.1.tgz", - "integrity": "sha512-WmRHqNVwn3kI3rKk1LsKcVgPBG6iLTBGC1iYOV3GQegwJ3E8yjzHytPt26VNzOWr1qu0xE03nK0Ug8S7T7oufw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/service-error-classification": "^4.0.1", - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/util-stream": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.0.2.tgz", - "integrity": "sha512-0eZ4G5fRzIoewtHtwaYyl8g2C+osYOT4KClXgfdNEDAgkbe2TYPqcnw4GAWabqkZCax2ihRGPe9LZnsPdIUIHA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/fetch-http-handler": "^5.0.1", - "@smithy/node-http-handler": "^4.0.2", - "@smithy/types": "^4.1.0", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-buffer-from": "^4.0.0", - "@smithy/util-hex-encoding": "^4.0.0", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/util-uri-escape": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz", - "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/util-utf8": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.0.0.tgz", - "integrity": "sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/util-buffer-from": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@smithy/util-waiter": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.0.2.tgz", - "integrity": "sha512-piUTHyp2Axx3p/kc2CIJkYSv0BAaheBQmbACZgQSSfWUumWNW+R1lL+H9PDBxKJkvOeEX+hKYEFiwO8xagL8AQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@smithy/abort-controller": "^4.0.1", - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@ts-graphviz/adapter": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@ts-graphviz/adapter/-/adapter-2.0.6.tgz", - "integrity": "sha512-kJ10lIMSWMJkLkkCG5gt927SnGZcBuG0s0HHswGzcHTgvtUe7yk5/3zTEr0bafzsodsOq5Gi6FhQeV775nC35Q==", - "extraneous": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ts-graphviz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/ts-graphviz" - } - ], - "license": "MIT", - "dependencies": { - "@ts-graphviz/common": "^2.1.5" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/@ts-graphviz/ast": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@ts-graphviz/ast/-/ast-2.0.7.tgz", - "integrity": "sha512-e6+2qtNV99UT6DJSoLbHfkzfyqY84aIuoV8Xlb9+hZAjgpum8iVHprGeAMQ4rF6sKUAxrmY8rfF/vgAwoPc3gw==", - "extraneous": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ts-graphviz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/ts-graphviz" - } - ], - "license": "MIT", - "dependencies": { - "@ts-graphviz/common": "^2.1.5" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/@ts-graphviz/common": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@ts-graphviz/common/-/common-2.1.5.tgz", - "integrity": "sha512-S6/9+T6x8j6cr/gNhp+U2olwo1n0jKj/682QVqsh7yXWV6ednHYqxFw0ZsY3LyzT0N8jaZ6jQY9YD99le3cmvg==", - "extraneous": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ts-graphviz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/ts-graphviz" - } - ], - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/@ts-graphviz/core": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@ts-graphviz/core/-/core-2.0.7.tgz", - "integrity": "sha512-w071DSzP94YfN6XiWhOxnLpYT3uqtxJBDYdh6Jdjzt+Ce6DNspJsPQgpC7rbts/B8tEkq0LHoYuIF/O5Jh5rPg==", - "extraneous": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ts-graphviz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/ts-graphviz" - } - ], - "license": "MIT", - "dependencies": { - "@ts-graphviz/ast": "^2.0.7", - "@ts-graphviz/common": "^2.1.5" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@types/archiver": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/@types/archiver/-/archiver-5.3.4.tgz", - "integrity": "sha512-Lj7fLBIMwYFgViVVZHEdExZC3lVYsl+QL0VmdNdIzGZH544jHveYWij6qdnBgJQDnR7pMKliN9z2cPZFEbhyPw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@types/readdir-glob": "*" - } - }, - "node_modules/cdk-assets/node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/cdk-assets/node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/cdk-assets/node_modules/@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@types/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "node_modules/cdk-assets/node_modules/@types/glob/node_modules/@types/node": { - "version": "22.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", - "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/cdk-assets/node_modules/@types/glob/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@types/graceful-fs": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/cdk-assets/node_modules/@types/graceful-fs/node_modules/@types/node": { - "version": "22.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", - "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/cdk-assets/node_modules/@types/graceful-fs/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/cdk-assets/node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/cdk-assets/node_modules/@types/jest": { - "version": "29.5.14", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", - "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@types/mime": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz", - "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@types/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@types/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@types/node": { - "version": "18.19.75", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.75.tgz", - "integrity": "sha512-UIksWtThob6ZVSyxcOqCLOUNg/dyO1Qvx4McgeuhrEtHTLFTf7BBhEazaE4K806FGTPtzd/2sE90qn4fVr7cyw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "node_modules/cdk-assets/node_modules/@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@types/readdir-glob": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@types/readdir-glob/-/readdir-glob-1.1.5.tgz", - "integrity": "sha512-raiuEPUYqXu+nvtY2Pe8s8FEmZ3x5yAH4VkLdihcPdalvsHltomrRC9BzuStrJ9yk06470hS0Crw0f1pXqD+Hg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/cdk-assets/node_modules/@types/readdir-glob/node_modules/@types/node": { - "version": "22.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", - "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/cdk-assets/node_modules/@types/readdir-glob/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@types/sinon": { - "version": "17.0.3", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.3.tgz", - "integrity": "sha512-j3uovdn8ewky9kRBG19bOwaZbexJu/XjtkHyjvUgt4xfPFz18dcORIMqnYh66Fx3Powhcr85NT5+er3+oViapw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@types/sinonjs__fake-timers": "*" - } - }, - "node_modules/cdk-assets/node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", - "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@types/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@types/uuid": { - "version": "9.0.8", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", - "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", - "dev": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@types/yargs": { - "version": "15.0.19", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", - "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/cdk-assets/node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.23.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.23.0.tgz", - "integrity": "sha512-vBz65tJgRrA1Q5gWlRfvoH+w943dq9K1p1yDBY2pc+a1nbBLZp7fB9+Hk8DaALUbzjqlMfgaqlVPT1REJdkt/w==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.23.0", - "@typescript-eslint/type-utils": "8.23.0", - "@typescript-eslint/utils": "8.23.0", - "@typescript-eslint/visitor-keys": "8.23.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.0.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" - } - }, - "node_modules/cdk-assets/node_modules/@typescript-eslint/parser": { - "version": "8.23.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.23.0.tgz", - "integrity": "sha512-h2lUByouOXFAlMec2mILeELUbME5SZRN/7R9Cw2RD2lRQQY08MWMM+PmVVKKJNK1aIwqTo9t/0CvOxwPbRIE2Q==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/scope-manager": "8.23.0", - "@typescript-eslint/types": "8.23.0", - "@typescript-eslint/typescript-estree": "8.23.0", - "@typescript-eslint/visitor-keys": "8.23.0", - "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": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" - } - }, - "node_modules/cdk-assets/node_modules/@typescript-eslint/scope-manager": { - "version": "8.23.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.23.0.tgz", - "integrity": "sha512-OGqo7+dXHqI7Hfm+WqkZjKjsiRtFUQHPdGMXzk5mYXhJUedO7e/Y7i8AK3MyLMgZR93TX4bIzYrfyVjLC+0VSw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.23.0", - "@typescript-eslint/visitor-keys": "8.23.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/cdk-assets/node_modules/@typescript-eslint/type-utils": { - "version": "8.23.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.23.0.tgz", - "integrity": "sha512-iIuLdYpQWZKbiH+RkCGc6iu+VwscP5rCtQ1lyQ7TYuKLrcZoeJVpcLiG8DliXVkUxirW/PWlmS+d6yD51L9jvA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/typescript-estree": "8.23.0", - "@typescript-eslint/utils": "8.23.0", - "debug": "^4.3.4", - "ts-api-utils": "^2.0.1" - }, - "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_modules/cdk-assets/node_modules/@typescript-eslint/types": { - "version": "8.23.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.23.0.tgz", - "integrity": "sha512-1sK4ILJbCmZOTt9k4vkoulT6/y5CHJ1qUYxqpF1K/DBAd8+ZUL4LlSCxOssuH5m4rUaaN0uS0HlVPvd45zjduQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/cdk-assets/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.23.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.23.0.tgz", - "integrity": "sha512-LcqzfipsB8RTvH8FX24W4UUFk1bl+0yTOf9ZA08XngFwMg4Kj8A+9hwz8Cr/ZS4KwHrmo9PJiLZkOt49vPnuvQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.23.0", - "@typescript-eslint/visitor-keys": "8.23.0", - "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.1" - }, - "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 <5.8.0" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/cdk-assets/node_modules/@typescript-eslint/utils": { - "version": "8.23.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.23.0.tgz", - "integrity": "sha512-uB/+PSo6Exu02b5ZEiVtmY6RVYO7YU5xqgzTIVZwTHvvK3HsL8tZZHFaTLFtRG3CsV4A5mhOv+NZx5BlhXPyIA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.23.0", - "@typescript-eslint/types": "8.23.0", - "@typescript-eslint/typescript-estree": "8.23.0" - }, - "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_modules/cdk-assets/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.23.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.23.0.tgz", - "integrity": "sha512-oWWhcWDLwDfu++BGTZcmXWqpwtkwb5o7fxUIGksMQQDSdPW9prsSnfIOZMlsj4vBOSrcnjIUZMiIjODgGosFhQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.23.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" - } - }, - "node_modules/cdk-assets/node_modules/@vitest/expect": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.5.tgz", - "integrity": "sha512-nNIOqupgZ4v5jWuQx2DSlHLEs7Q4Oh/7AYwNyE+k0UQzG7tSmjPXShUikn1mpNGzYEN2jJbTvLejwShMitovBA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@vitest/spy": "3.0.5", - "@vitest/utils": "3.0.5", - "chai": "^5.1.2", - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/cdk-assets/node_modules/@vitest/pretty-format": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.5.tgz", - "integrity": "sha512-CjUtdmpOcm4RVtB+up8r2vVDLR16Mgm/bYdkGFe3Yj/scRfCpbSi2W/BDSDcFK7ohw8UXvjMbOp9H4fByd/cOA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/cdk-assets/node_modules/@vitest/spy": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.5.tgz", - "integrity": "sha512-5fOzHj0WbUNqPK6blI/8VzZdkBlQLnT25knX0r4dbZI9qoZDf3qAdjoMmDcLG5A83W6oUUFJgUd0EYBc2P5xqg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "tinyspy": "^3.0.2" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/cdk-assets/node_modules/@vitest/utils": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.5.tgz", - "integrity": "sha512-N9AX0NUoUtVwKwy21JtwzaqR5L5R5A99GAbrHfCCXK1lp593i/3AZAXhSP43wRQuxYsflrdzEfXZFo1reR1Nkg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "3.0.5", - "loupe": "^3.1.2", - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/cdk-assets/node_modules/@vue/compiler-core": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.13.tgz", - "integrity": "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.25.3", - "@vue/shared": "3.5.13", - "entities": "^4.5.0", - "estree-walker": "^2.0.2", - "source-map-js": "^1.2.0" - } - }, - "node_modules/cdk-assets/node_modules/@vue/compiler-dom": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz", - "integrity": "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@vue/compiler-core": "3.5.13", - "@vue/shared": "3.5.13" - } - }, - "node_modules/cdk-assets/node_modules/@vue/compiler-sfc": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz", - "integrity": "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.25.3", - "@vue/compiler-core": "3.5.13", - "@vue/compiler-dom": "3.5.13", - "@vue/compiler-ssr": "3.5.13", - "@vue/shared": "3.5.13", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.11", - "postcss": "^8.4.48", - "source-map-js": "^1.2.0" - } - }, - "node_modules/cdk-assets/node_modules/@vue/compiler-ssr": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz", - "integrity": "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@vue/compiler-dom": "3.5.13", - "@vue/shared": "3.5.13" - } - }, - "node_modules/cdk-assets/node_modules/@vue/shared": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.13.tgz", - "integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", - "extraneous": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/cdk-assets/node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "extraneous": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/cdk-assets/node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/cdk-assets/node_modules/add-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", - "integrity": "sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/agent-base": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", - "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, - "node_modules/cdk-assets/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/cdk-assets/node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "extraneous": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/cdk-assets/node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cdk-assets/node_modules/app-module-path": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/app-module-path/-/app-module-path-2.2.0.tgz", - "integrity": "sha512-gkco+qxENJV+8vFcDiiFhuoSvRXb2a/QPqpSoWhVz829VNJfOTnELbBmPmNKFxf3xdNnw4DWCkzkDaavcX/1YQ==", - "extraneous": true, - "license": "BSD-2-Clause" - }, - "node_modules/cdk-assets/node_modules/archiver": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", - "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "archiver-utils": "^2.1.0", - "async": "^3.2.4", - "buffer-crc32": "^0.2.1", - "readable-stream": "^3.6.0", - "readdir-glob": "^1.1.2", - "tar-stream": "^2.2.0", - "zip-stream": "^4.1.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/cdk-assets/node_modules/archiver-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", - "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", - "dev": true, - "license": "MIT", - "dependencies": { - "glob": "^7.1.4", - "graceful-fs": "^4.2.0", - "lazystream": "^1.0.0", - "lodash.defaults": "^4.2.0", - "lodash.difference": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.union": "^4.6.0", - "normalize-path": "^3.0.0", - "readable-stream": "^2.0.0" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/cdk-assets/node_modules/archiver-utils/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/archiver-utils/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/cdk-assets/node_modules/archiver-utils/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/cdk-assets/node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/cdk-assets/node_modules/array-buffer-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", - "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "is-array-buffer": "^3.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/array-ify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "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" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/array-timsort": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", - "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/array.prototype.flat": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", - "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/array.prototype.flatmap": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", - "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/arraybuffer.prototype.slice": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", - "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/cdk-assets/node_modules/ast-module-types": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ast-module-types/-/ast-module-types-6.0.1.tgz", - "integrity": "sha512-WHw67kLXYbZuHTmcdbIrVArCq5wxo6NEuj3hiYAWr8mwJeC+C2mMCIBIWCiDoCye/OF/xelc+teJ1ERoWmnEIA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "dev": true, - "license": "MIT" - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/cdk-assets/node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "extraneous": true, - "license": "ISC", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/aws-sdk-client-mock": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/aws-sdk-client-mock/-/aws-sdk-client-mock-4.1.0.tgz", - "integrity": "sha512-h/tOYTkXEsAcV3//6C1/7U4ifSpKyJvb6auveAepqqNJl6TdZaPFEtKjBQNf8UxQdDP850knB2i/whq4zlsxJw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@types/sinon": "^17.0.3", - "sinon": "^18.0.1", - "tslib": "^2.1.0" - } - }, - "node_modules/cdk-assets/node_modules/aws-sdk-client-mock-jest": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/aws-sdk-client-mock-jest/-/aws-sdk-client-mock-jest-4.1.0.tgz", - "integrity": "sha512-+g4a5Hp+MmPqqNnvwfLitByggrqf+xSbk1pm6fBYHNcon6+aQjL5iB+3YB6HuGPemY+/mUKN34iP62S14R61bA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@vitest/expect": ">1.6.0", - "expect": ">28.1.3", - "tslib": "^2.1.0" - }, - "peerDependencies": { - "aws-sdk-client-mock": "4.1.0", - "vitest": ">1.6.0" - }, - "peerDependenciesMeta": { - "vitest": { - "optional": true - } - } - }, - "node_modules/cdk-assets/node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/cdk-assets/node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "extraneous": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "extraneous": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/babel-plugin-istanbul/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "extraneous": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/cdk-assets/node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/babel-preset-current-node-syntax": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", - "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/cdk-assets/node_modules/babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/cdk-assets/node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/cdk-assets/node_modules/bl/node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/cdk-assets/node_modules/bowser": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", - "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", - "dev": true, - "license": "MIT" - }, - "node_modules/cdk-assets/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==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/cdk-assets/node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/browserslist": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", - "extraneous": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/cdk-assets/node_modules/bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "fast-json-stable-stringify": "2.x" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/cdk-assets/node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "node-int64": "^0.4.0" - } - }, - "node_modules/cdk-assets/node_modules/buffer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", - "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", - "dev": true, - "license": "MIT", - "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "node_modules/cdk-assets/node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/cdk-assets/node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/camelcase-keys/node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/caniuse-lite": { - "version": "1.0.30001697", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001697.tgz", - "integrity": "sha512-GwNPlWJin8E+d7Gxq96jxM6w0w+VFeyyXRsjU58emtkYqnbwHqXm5uT2uCmO0RQE9htWknOP4xtBlLmM/gWxvQ==", - "extraneous": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/cdk-assets/node_modules/case": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/case/-/case-1.6.3.tgz", - "integrity": "sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==", - "extraneous": true, - "license": "(MIT OR GPL-3.0-or-later)", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/cdk-assets/node_modules/chai": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz", - "integrity": "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cdk-assets/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/cdk-assets/node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/cdk-assets/node_modules/check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 16" - } - }, - "node_modules/cdk-assets/node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "extraneous": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/cjs-module-lexer": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", - "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/cdk-assets/node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/cdk-assets/node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/cdk-assets/node_modules/collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/cdk-assets/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/cdk-assets/node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/comment-json": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.2.2.tgz", - "integrity": "sha512-H8T+kl3nZesZu41zO2oNXIJWojNeK3mHxCLrsBNu6feksBXsgb+PtYz5daP5P86A0F3sz3840KVYehr04enISQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "array-timsort": "^1.0.3", - "core-util-is": "^1.0.3", - "esprima": "^4.0.1", - "has-own-prop": "^2.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/cdk-assets/node_modules/commit-and-tag-version": { - "version": "12.5.0", - "resolved": "https://registry.npmjs.org/commit-and-tag-version/-/commit-and-tag-version-12.5.0.tgz", - "integrity": "sha512-Ll7rkKntH20iEFOPUT4e503Jf3J0J8jSN+aSeHuvNdtv4xmv9kSLSBg2CWsMVihwF3J2WvMHBEUSCKuDNesiTA==", - "extraneous": true, - "license": "ISC", - "dependencies": { - "chalk": "^2.4.2", - "conventional-changelog": "4.0.0", - "conventional-changelog-config-spec": "2.1.0", - "conventional-changelog-conventionalcommits": "6.1.0", - "conventional-recommended-bump": "7.0.1", - "detect-indent": "^6.0.0", - "detect-newline": "^3.1.0", - "dotgitignore": "^2.1.0", - "figures": "^3.1.0", - "find-up": "^5.0.0", - "git-semver-tags": "^5.0.0", - "jsdom": "^25.0.0", - "semver": "^7.6.3", - "w3c-xmlserializer": "^5.0.0", - "yaml": "^2.4.1", - "yargs": "^17.7.2" - }, - "bin": { - "commit-and-tag-version": "bin/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/commit-and-tag-version/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/commit-and-tag-version/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/commit-and-tag-version/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "extraneous": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cdk-assets/node_modules/commit-and-tag-version/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/cdk-assets/node_modules/commit-and-tag-version/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/commit-and-tag-version/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/commit-and-tag-version/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/commit-and-tag-version/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/commit-and-tag-version/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/commit-and-tag-version/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/commit-and-tag-version/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/commit-and-tag-version/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cdk-assets/node_modules/commit-and-tag-version/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "extraneous": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/cdk-assets/node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/compare-func": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", - "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "array-ify": "^1.0.0", - "dot-prop": "^5.1.0" - } - }, - "node_modules/cdk-assets/node_modules/compress-commons": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz", - "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-crc32": "^0.2.13", - "crc32-stream": "^4.0.2", - "normalize-path": "^3.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/cdk-assets/node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/concat-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", - "engines": [ - "node >= 6.0" - ], - "extraneous": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/cdk-assets/node_modules/constructs": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.4.2.tgz", - "integrity": "sha512-wsNxBlAott2qg8Zv87q3eYZYgheb9lchtBfjHzzLHtXbttwSrHPs1NNQbBrmbb1YZvYg2+Vh0Dor76w4mFxJkA==", - "extraneous": true, - "license": "Apache-2.0" - }, - "node_modules/cdk-assets/node_modules/conventional-changelog": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-4.0.0.tgz", - "integrity": "sha512-JbZjwE1PzxQCvm+HUTIr+pbSekS8qdOZzMakdFyPtdkEWwFvwEJYONzjgMm0txCb2yBcIcfKDmg8xtCKTdecNQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "conventional-changelog-angular": "^6.0.0", - "conventional-changelog-atom": "^3.0.0", - "conventional-changelog-codemirror": "^3.0.0", - "conventional-changelog-conventionalcommits": "^6.0.0", - "conventional-changelog-core": "^5.0.0", - "conventional-changelog-ember": "^3.0.0", - "conventional-changelog-eslint": "^4.0.0", - "conventional-changelog-express": "^3.0.0", - "conventional-changelog-jquery": "^4.0.0", - "conventional-changelog-jshint": "^3.0.0", - "conventional-changelog-preset-loader": "^3.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/cdk-assets/node_modules/conventional-changelog-angular": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-6.0.0.tgz", - "integrity": "sha512-6qLgrBF4gueoC7AFVHu51nHL9pF9FRjXrH+ceVf7WmAfH3gs+gEYOkvxhjMPjZu57I4AGUGoNTY8V7Hrgf1uqg==", - "extraneous": true, - "license": "ISC", - "dependencies": { - "compare-func": "^2.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/cdk-assets/node_modules/conventional-changelog-atom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-3.0.0.tgz", - "integrity": "sha512-pnN5bWpH+iTUWU3FaYdw5lJmfWeqSyrUkG+wyHBI9tC1dLNnHkbAOg1SzTQ7zBqiFrfo55h40VsGXWMdopwc5g==", - "extraneous": true, - "license": "ISC", - "engines": { - "node": ">=14" - } - }, - "node_modules/cdk-assets/node_modules/conventional-changelog-codemirror": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-3.0.0.tgz", - "integrity": "sha512-wzchZt9HEaAZrenZAUUHMCFcuYzGoZ1wG/kTRMICxsnW5AXohYMRxnyecP9ob42Gvn5TilhC0q66AtTPRSNMfw==", - "extraneous": true, - "license": "ISC", - "engines": { - "node": ">=14" - } - }, - "node_modules/cdk-assets/node_modules/conventional-changelog-config-spec": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.0.tgz", - "integrity": "sha512-IpVePh16EbbB02V+UA+HQnnPIohgXvJRxHcS5+Uwk4AT5LjzCZJm5sp/yqs5C6KZJ1jMsV4paEV13BN1pvDuxQ==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/conventional-changelog-conventionalcommits": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-6.1.0.tgz", - "integrity": "sha512-3cS3GEtR78zTfMzk0AizXKKIdN4OvSh7ibNz6/DPbhWWQu7LqE/8+/GqSodV+sywUR2gpJAdP/1JFf4XtN7Zpw==", - "extraneous": true, - "license": "ISC", - "dependencies": { - "compare-func": "^2.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/cdk-assets/node_modules/conventional-changelog-core": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-5.0.2.tgz", - "integrity": "sha512-RhQOcDweXNWvlRwUDCpaqXzbZemKPKncCWZG50Alth72WITVd6nhVk9MJ6w1k9PFNBcZ3YwkdkChE+8+ZwtUug==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "add-stream": "^1.0.0", - "conventional-changelog-writer": "^6.0.0", - "conventional-commits-parser": "^4.0.0", - "dateformat": "^3.0.3", - "get-pkg-repo": "^4.2.1", - "git-raw-commits": "^3.0.0", - "git-remote-origin-url": "^2.0.0", - "git-semver-tags": "^5.0.0", - "normalize-package-data": "^3.0.3", - "read-pkg": "^3.0.0", - "read-pkg-up": "^3.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/cdk-assets/node_modules/conventional-changelog-core/node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "extraneous": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cdk-assets/node_modules/conventional-changelog-ember": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-3.0.0.tgz", - "integrity": "sha512-7PYthCoSxIS98vWhVcSphMYM322OxptpKAuHYdVspryI0ooLDehRXWeRWgN+zWSBXKl/pwdgAg8IpLNSM1/61A==", - "extraneous": true, - "license": "ISC", - "engines": { - "node": ">=14" - } - }, - "node_modules/cdk-assets/node_modules/conventional-changelog-eslint": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-4.0.0.tgz", - "integrity": "sha512-nEZ9byP89hIU0dMx37JXQkE1IpMmqKtsaR24X7aM3L6Yy/uAtbb+ogqthuNYJkeO1HyvK7JsX84z8649hvp43Q==", - "extraneous": true, - "license": "ISC", - "engines": { - "node": ">=14" - } - }, - "node_modules/cdk-assets/node_modules/conventional-changelog-express": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-3.0.0.tgz", - "integrity": "sha512-HqxihpUMfIuxvlPvC6HltA4ZktQEUan/v3XQ77+/zbu8No/fqK3rxSZaYeHYant7zRxQNIIli7S+qLS9tX9zQA==", - "extraneous": true, - "license": "ISC", - "engines": { - "node": ">=14" - } - }, - "node_modules/cdk-assets/node_modules/conventional-changelog-jquery": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-4.0.0.tgz", - "integrity": "sha512-TTIN5CyzRMf8PUwyy4IOLmLV2DFmPtasKN+x7EQKzwSX8086XYwo+NeaeA3VUT8bvKaIy5z/JoWUvi7huUOgaw==", - "extraneous": true, - "license": "ISC", - "engines": { - "node": ">=14" - } - }, - "node_modules/cdk-assets/node_modules/conventional-changelog-jshint": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-3.0.0.tgz", - "integrity": "sha512-bQof4byF4q+n+dwFRkJ/jGf9dCNUv4/kCDcjeCizBvfF81TeimPZBB6fT4HYbXgxxfxWXNl/i+J6T0nI4by6DA==", - "extraneous": true, - "license": "ISC", - "dependencies": { - "compare-func": "^2.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/cdk-assets/node_modules/conventional-changelog-preset-loader": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-3.0.0.tgz", - "integrity": "sha512-qy9XbdSLmVnwnvzEisjxdDiLA4OmV3o8db+Zdg4WiFw14fP3B6XNz98X0swPPpkTd/pc1K7+adKgEDM1JCUMiA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=14" - } - }, - "node_modules/cdk-assets/node_modules/conventional-changelog-writer": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-6.0.1.tgz", - "integrity": "sha512-359t9aHorPw+U+nHzUXHS5ZnPBOizRxfQsWT5ZDHBfvfxQOAik+yfuhKXG66CN5LEWPpMNnIMHUTCKeYNprvHQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "conventional-commits-filter": "^3.0.0", - "dateformat": "^3.0.3", - "handlebars": "^4.7.7", - "json-stringify-safe": "^5.0.1", - "meow": "^8.1.2", - "semver": "^7.0.0", - "split": "^1.0.1" - }, - "bin": { - "conventional-changelog-writer": "cli.js" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/cdk-assets/node_modules/conventional-commits-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-3.0.0.tgz", - "integrity": "sha512-1ymej8b5LouPx9Ox0Dw/qAO2dVdfpRFq28e5Y0jJEU8ZrLdy0vOSkkIInwmxErFGhg6SALro60ZrwYFVTUDo4Q==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "lodash.ismatch": "^4.4.0", - "modify-values": "^1.0.1" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/cdk-assets/node_modules/conventional-commits-parser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-4.0.0.tgz", - "integrity": "sha512-WRv5j1FsVM5FISJkoYMR6tPk07fkKT0UodruX4je86V4owk451yjXAKzKAPOs9l7y59E2viHUS9eQ+dfUA9NSg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "is-text-path": "^1.0.1", - "JSONStream": "^1.3.5", - "meow": "^8.1.2", - "split2": "^3.2.2" - }, - "bin": { - "conventional-commits-parser": "cli.js" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/cdk-assets/node_modules/conventional-recommended-bump": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-7.0.1.tgz", - "integrity": "sha512-Ft79FF4SlOFvX4PkwFDRnaNiIVX7YbmqGU0RwccUaiGvgp3S0a8ipR2/Qxk31vclDNM+GSdJOVs2KrsUCjblVA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "concat-stream": "^2.0.0", - "conventional-changelog-preset-loader": "^3.0.0", - "conventional-commits-filter": "^3.0.0", - "conventional-commits-parser": "^4.0.0", - "git-raw-commits": "^3.0.0", - "git-semver-tags": "^5.0.0", - "meow": "^8.1.2" - }, - "bin": { - "conventional-recommended-bump": "cli.js" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/cdk-assets/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/crc-32": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", - "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "crc32": "bin/crc32.njs" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/cdk-assets/node_modules/crc32-stream": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz", - "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", - "dev": true, - "license": "MIT", - "dependencies": { - "crc-32": "^1.2.0", - "readable-stream": "^3.4.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/cdk-assets/node_modules/create-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" - }, - "bin": { - "create-jest": "bin/create-jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cdk-assets/node_modules/cssstyle": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.2.1.tgz", - "integrity": "sha512-9+vem03dMXG7gDmZ62uqmRiMRNtinIZ9ZyuF6BdxzfOD+FdN5hretzynkn0ReS2DO2GSw76RWHs0UmJPI2zUjw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@asamuzakjp/css-color": "^2.8.2", - "rrweb-cssom": "^0.8.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/cssstyle/node_modules/rrweb-cssom": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", - "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/dargs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", - "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/data-urls": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", - "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/data-view-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", - "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/inspect-js" - } - }, - "node_modules/cdk-assets/node_modules/data-view-byte-offset": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", - "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/cdk-assets/node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/decimal.js": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.5.0.tgz", - "integrity": "sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/dedent": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", - "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", - "extraneous": true, - "license": "MIT", - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/cdk-assets/node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/cdk-assets/node_modules/deep-is": { - "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==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/cdk-assets/node_modules/dependency-tree": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/dependency-tree/-/dependency-tree-11.0.2.tgz", - "integrity": "sha512-eQPTn16WpphktLNvG/h0vQyKCCDpR4x6wYdQOM1aJBiCqWzCRYV7Yr9F7pv/o0DcMpamazd5hE+B2RvITXeNaw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "commander": "^12.1.0", - "filing-cabinet": "^5.0.2", - "precinct": "^12.1.3", - "typescript": "^5.7.3" - }, - "bin": { - "dependency-tree": "bin/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/detective-amd": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/detective-amd/-/detective-amd-6.0.1.tgz", - "integrity": "sha512-TtyZ3OhwUoEEIhTFoc1C9IyJIud3y+xYkSRjmvCt65+ycQuc3VcBrPRTMWoO/AnuCyOB8T5gky+xf7Igxtjd3g==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "ast-module-types": "^6.0.1", - "escodegen": "^2.1.0", - "get-amd-module-type": "^6.0.1", - "node-source-walk": "^7.0.1" - }, - "bin": { - "detective-amd": "bin/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/detective-cjs": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/detective-cjs/-/detective-cjs-6.0.1.tgz", - "integrity": "sha512-tLTQsWvd2WMcmn/60T2inEJNhJoi7a//PQ7DwRKEj1yEeiQs4mrONgsUtEJKnZmrGWBBmE0kJ1vqOG/NAxwaJw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "ast-module-types": "^6.0.1", - "node-source-walk": "^7.0.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/detective-es6": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/detective-es6/-/detective-es6-5.0.1.tgz", - "integrity": "sha512-XusTPuewnSUdoxRSx8OOI6xIA/uld/wMQwYsouvFN2LAg7HgP06NF1lHRV3x6BZxyL2Kkoih4ewcq8hcbGtwew==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "node-source-walk": "^7.0.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/detective-postcss": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/detective-postcss/-/detective-postcss-7.0.1.tgz", - "integrity": "sha512-bEOVpHU9picRZux5XnwGsmCN4+8oZo7vSW0O0/Enq/TO5R2pIAP2279NsszpJR7ocnQt4WXU0+nnh/0JuK4KHQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "is-url": "^1.2.4", - "postcss-values-parser": "^6.0.2" - }, - "engines": { - "node": "^14.0.0 || >=16.0.0" - }, - "peerDependencies": { - "postcss": "^8.4.47" - } - }, - "node_modules/cdk-assets/node_modules/detective-sass": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/detective-sass/-/detective-sass-6.0.1.tgz", - "integrity": "sha512-jSGPO8QDy7K7pztUmGC6aiHkexBQT4GIH+mBAL9ZyBmnUIOFbkfZnO8wPRRJFP/QP83irObgsZHCoDHZ173tRw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "gonzales-pe": "^4.3.0", - "node-source-walk": "^7.0.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/detective-scss": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/detective-scss/-/detective-scss-5.0.1.tgz", - "integrity": "sha512-MAyPYRgS6DCiS6n6AoSBJXLGVOydsr9huwXORUlJ37K3YLyiN0vYHpzs3AdJOgHobBfispokoqrEon9rbmKacg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "gonzales-pe": "^4.3.0", - "node-source-walk": "^7.0.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/detective-stylus": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/detective-stylus/-/detective-stylus-5.0.1.tgz", - "integrity": "sha512-Dgn0bUqdGbE3oZJ+WCKf8Dmu7VWLcmRJGc6RCzBgG31DLIyai9WAoEhYRgIHpt/BCRMrnXLbGWGPQuBUrnF0TA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/detective-typescript": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/detective-typescript/-/detective-typescript-13.0.1.tgz", - "integrity": "sha512-k+1EbJESP/PVA3G+Squsd7EjCoitCn3ZWdpl4ReWR8TyEfdF7AP7yMhlpbYXOw7i5VBFY2tOeOmKZD2XtsCpVQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/typescript-estree": "^7.18.0", - "ast-module-types": "^6.0.1", - "node-source-walk": "^7.0.1" - }, - "engines": { - "node": "^14.14.0 || >=16.0.0" - }, - "peerDependencies": { - "typescript": "^5.4.4" - } - }, - "node_modules/cdk-assets/node_modules/detective-typescript/node_modules/@typescript-eslint/types": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", - "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/cdk-assets/node_modules/detective-typescript/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", - "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", - "extraneous": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/cdk-assets/node_modules/detective-typescript/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", - "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/cdk-assets/node_modules/detective-typescript/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==", - "extraneous": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/cdk-assets/node_modules/detective-typescript/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "extraneous": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/cdk-assets/node_modules/detective-typescript/node_modules/ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "node_modules/cdk-assets/node_modules/detective-vue2": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detective-vue2/-/detective-vue2-2.1.2.tgz", - "integrity": "sha512-/uDzKDYTeLJTsgSJR5zNxj48umamdvn2OftjgwVxa2Ir2JjFjlgGRcWU2lJ354enjiGbRe1ZIapz/6s+e5lthw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@dependents/detective-less": "^5.0.1", - "@vue/compiler-sfc": "^3.5.13", - "detective-es6": "^5.0.1", - "detective-sass": "^6.0.1", - "detective-scss": "^5.0.1", - "detective-stylus": "^5.0.1", - "detective-typescript": "^13.0.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "typescript": "^5.4.4" - } - }, - "node_modules/cdk-assets/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "extraneous": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/cdk-assets/node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/dir-glob/node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/dotgitignore": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/dotgitignore/-/dotgitignore-2.1.0.tgz", - "integrity": "sha512-sCm11ak2oY6DglEPpCB8TixLjWAxd3kJTs6UIcSasNYxXdFPV+YKlye92c8H4kKFqV5qYMIh7d+cYecEg0dIkA==", - "extraneous": true, - "license": "ISC", - "dependencies": { - "find-up": "^3.0.0", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/dotgitignore/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/dotgitignore/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/dotgitignore/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/dotgitignore/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/cdk-assets/node_modules/ejs": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", - "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "jake": "^10.8.5" - }, - "bin": { - "ejs": "bin/cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/node_modules/electron-to-chromium": { - "version": "1.5.92", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.92.tgz", - "integrity": "sha512-BeHgmNobs05N1HMmMZ7YIuHfYBGlq/UmvlsTgg+fsbFs9xVMj+xJHFg19GN04+9Q+r8Xnh9LXqaYIyEWElnNgQ==", - "extraneous": true, - "license": "ISC" - }, - "node_modules/cdk-assets/node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/cdk-assets/node_modules/emoji-regex": { - "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, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/cdk-assets/node_modules/enhanced-resolve": { - "version": "5.18.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", - "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/cdk-assets/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "extraneous": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/cdk-assets/node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": 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", - "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-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-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-regex": "^1.2.1", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.0", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.3", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.18" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/cdk-assets/node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/cdk-assets/node_modules/es-object-atoms": { - "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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/cdk-assets/node_modules/es-set-tostringtag": { - "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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.0" - } - }, - "node_modules/cdk-assets/node_modules/es-to-primitive": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", - "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7", - "is-date-object": "^1.0.5", - "is-symbol": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/cdk-assets/node_modules/escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "extraneous": true, - "license": "BSD-2-Clause", - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/cdk-assets/node_modules/eslint": { - "version": "9.19.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz", - "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==", - "extraneous": 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", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.1", - "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "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", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } - } - }, - "node_modules/cdk-assets/node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", - "extraneous": true, - "license": "MIT", - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/cdk-assets/node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/cdk-assets/node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": 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" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" - }, - "peerDependencies": { - "eslint": "*", - "eslint-plugin-import": "*", - "eslint-plugin-import-x": "*" - }, - "peerDependenciesMeta": { - "eslint-plugin-import": { - "optional": true - }, - "eslint-plugin-import-x": { - "optional": true - } - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/cdk-assets/node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": 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", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.0", - "hasown": "^2.0.2", - "is-core-module": "^2.15.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", - "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.8", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" - } - }, - "node_modules/cdk-assets/node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/cdk-assets/node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "extraneous": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/cdk-assets/node_modules/eslint-plugin-prettier": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz", - "integrity": "sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.9.1" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint-plugin-prettier" - }, - "peerDependencies": { - "@types/eslint": ">=8.0.0", - "eslint": ">=8.0.0", - "eslint-config-prettier": "*", - "prettier": ">=3.0.0" - }, - "peerDependenciesMeta": { - "@types/eslint": { - "optional": true - }, - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/cdk-assets/node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/eslint/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/eslint/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/eslint/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/eslint/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/espree": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", - "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", - "extraneous": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.14.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/cdk-assets/node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "extraneous": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "extraneous": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/cdk-assets/node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "extraneous": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/cdk-assets/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "extraneous": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/cdk-assets/node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "extraneous": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/cdk-assets/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/cdk-assets/node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "extraneous": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/cdk-assets/node_modules/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/fast-deep-equal": { - "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==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "extraneous": true, - "license": "Apache-2.0" - }, - "node_modules/cdk-assets/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==", - "extraneous": 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.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/cdk-assets/node_modules/fast-json-patch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.1.tgz", - "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/fast-json-stable-stringify": { - "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==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/fast-xml-parser": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", - "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - }, - { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" - } - ], - "license": "MIT", - "dependencies": { - "strnum": "^1.0.5" - }, - "bin": { - "fxparser": "src/cli/cli.js" - } - }, - "node_modules/cdk-assets/node_modules/fastq": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz", - "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==", - "extraneous": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/cdk-assets/node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "bser": "2.1.1" - } - }, - "node_modules/cdk-assets/node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/cdk-assets/node_modules/filelist": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", - "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "minimatch": "^5.0.1" - } - }, - "node_modules/cdk-assets/node_modules/filelist/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "extraneous": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cdk-assets/node_modules/filing-cabinet": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/filing-cabinet/-/filing-cabinet-5.0.3.tgz", - "integrity": "sha512-PlPcMwVWg60NQkhvfoxZs4wEHjhlOO/y7OAm4sKM60o1Z9nttRY4mcdQxp/iZ+kg/Vv6Hw1OAaTbYVM9DA9pYg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "app-module-path": "^2.2.0", - "commander": "^12.1.0", - "enhanced-resolve": "^5.18.0", - "module-definition": "^6.0.1", - "module-lookup-amd": "^9.0.3", - "resolve": "^1.22.10", - "resolve-dependency-path": "^4.0.1", - "sass-lookup": "^6.1.0", - "stylus-lookup": "^6.1.0", - "tsconfig-paths": "^4.2.0", - "typescript": "^5.7.3" - }, - "bin": { - "filing-cabinet": "bin/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/filing-cabinet/node_modules/tsconfig-paths": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", - "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "json5": "^2.2.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/find-up/node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "ISC" - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/cdk-assets/node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cdk-assets/node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC" - }, - "node_modules/cdk-assets/node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "extraneous": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/function.prototype.name": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", - "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "functions-have-names": "^1.2.3", - "hasown": "^2.0.2", - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "extraneous": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/cdk-assets/node_modules/get-amd-module-type": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-amd-module-type/-/get-amd-module-type-6.0.1.tgz", - "integrity": "sha512-MtjsmYiCXcYDDrGqtNbeIYdAl85n+5mSv2r3FbzER/YV3ZILw4HNNIw34HuV5pyl0jzs6GFYU1VHVEefhgcNHQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "ast-module-types": "^6.0.1", - "node-source-walk": "^7.0.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "function-bind": "^1.1.2", - "get-proto": "^1.0.0", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/get-own-enumerable-property-symbols": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", - "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", - "extraneous": true, - "license": "ISC" - }, - "node_modules/cdk-assets/node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/cdk-assets/node_modules/get-pkg-repo": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", - "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@hutson/parse-repository-url": "^3.0.0", - "hosted-git-info": "^4.0.0", - "through2": "^2.0.0", - "yargs": "^16.2.0" - }, - "bin": { - "get-pkg-repo": "src/cli.js" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/cdk-assets/node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/cdk-assets/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/get-symbol-description": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", - "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/cdk-assets/node_modules/git-raw-commits": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-3.0.0.tgz", - "integrity": "sha512-b5OHmZ3vAgGrDn/X0kS+9qCfNKWe4K/jFnhwzVWWg0/k5eLa3060tZShrRg8Dja5kPc+YjS0Gc6y7cRr44Lpjw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "dargs": "^7.0.0", - "meow": "^8.1.2", - "split2": "^3.2.2" - }, - "bin": { - "git-raw-commits": "cli.js" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/cdk-assets/node_modules/git-remote-origin-url": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", - "integrity": "sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "gitconfiglocal": "^1.0.0", - "pify": "^2.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/git-remote-origin-url/node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/node_modules/git-semver-tags": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-5.0.1.tgz", - "integrity": "sha512-hIvOeZwRbQ+7YEUmCkHqo8FOLQZCEn18yevLHADlFPZY02KJGsu5FZt9YW/lybfK2uhWFI7Qg/07LekJiTv7iA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "meow": "^8.1.2", - "semver": "^7.0.0" - }, - "bin": { - "git-semver-tags": "cli.js" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/cdk-assets/node_modules/gitconfiglocal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", - "integrity": "sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==", - "extraneous": true, - "license": "BSD", - "dependencies": { - "ini": "^1.3.2" - } - }, - "node_modules/cdk-assets/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/cdk-assets/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "extraneous": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/cdk-assets/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/gonzales-pe": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.3.0.tgz", - "integrity": "sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "gonzales": "bin/gonzales.js" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/cdk-assets/node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/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, - "license": "ISC" - }, - "node_modules/cdk-assets/node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/cdk-assets/node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/has-own-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz", - "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/has-proto": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", - "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/cdk-assets/node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "extraneous": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cdk-assets/node_modules/html-encoding-sniffer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", - "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "whatwg-encoding": "^3.1.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/cdk-assets/node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/cdk-assets/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "extraneous": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/cdk-assets/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/cdk-assets/node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/cdk-assets/node_modules/immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/import-local": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/cdk-assets/node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/cdk-assets/node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/cdk-assets/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "extraneous": true, - "license": "ISC" - }, - "node_modules/cdk-assets/node_modules/internal-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", - "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/cdk-assets/node_modules/interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/cdk-assets/node_modules/is-array-buffer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", - "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/is-async-function": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", - "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "async-function": "^1.0.0", - "call-bound": "^1.0.3", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/is-bigint": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", - "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "has-bigints": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/is-boolean-object": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", - "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "semver": "^7.6.3" - } - }, - "node_modules/cdk-assets/node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/is-data-view": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", - "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/is-date-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", - "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/node_modules/is-finalizationregistry": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", - "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "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" - } - }, - "node_modules/cdk-assets/node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/is-generator-function": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", - "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "get-proto": "^1.0.0", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/cdk-assets/node_modules/is-number-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", - "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/is-regex": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/node_modules/is-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/is-shared-array-buffer": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", - "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/is-string": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", - "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/is-symbol": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", - "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-symbols": "^1.1.0", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/is-text-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", - "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "text-extensions": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/node_modules/is-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/is-url-superb": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-url-superb/-/is-url-superb-4.0.0.tgz", - "integrity": "sha512-GI+WjezhPPcbM+tqE9LnmsY5qqjwHzTvjJ36wxYX5ujNXefSUJ/T17r5bqDV8yLhcgB59KTPNOc9O9cmHTPWsA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/is-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/is-weakref": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", - "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/is-weakset": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", - "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "extraneous": true, - "license": "ISC" - }, - "node_modules/cdk-assets/node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "extraneous": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/istanbul-lib-instrument": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", - "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", - "extraneous": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cdk-assets/node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "extraneous": true, - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cdk-assets/node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "extraneous": true, - "license": "BSD-3-Clause", - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cdk-assets/node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", - "extraneous": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/jake": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", - "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "async": "^3.2.3", - "chalk": "^4.0.2", - "filelist": "^1.0.4", - "minimatch": "^3.1.2" - }, - "bin": { - "jake": "bin/cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cdk-assets/node_modules/jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/cdk-assets/node_modules/jest-changed-files": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", - "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-circus": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", - "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.7.0", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.7.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-circus/node_modules/@types/node": { - "version": "22.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", - "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-circus/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/jest-cli": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", - "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "create-jest": "^29.7.0", - "exit": "^0.1.2", - "import-local": "^3.0.2", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/cdk-assets/node_modules/jest-cli/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "extraneous": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cdk-assets/node_modules/jest-cli/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cdk-assets/node_modules/jest-cli/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "extraneous": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/cdk-assets/node_modules/jest-config": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/cdk-assets/node_modules/jest-config/node_modules/@types/node": { - "version": "22.13.1", - "extraneous": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-config/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-docblock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", - "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "detect-newline": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-each": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", - "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-environment-node/node_modules/@types/node": { - "version": "22.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", - "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-environment-node/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, - "node_modules/cdk-assets/node_modules/jest-haste-map/node_modules/@types/node": { - "version": "22.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", - "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-haste-map/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/jest-junit": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-16.0.0.tgz", - "integrity": "sha512-A94mmw6NfJab4Fg/BlvVOUXzXgF0XIH6EmTgJ5NDPp4xoKq0Kr7sErb+4Xs9nZvu58pJojz5RFGpqnZYJTrRfQ==", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "mkdirp": "^1.0.4", - "strip-ansi": "^6.0.1", - "uuid": "^8.3.2", - "xml": "^1.0.1" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-junit/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "extraneous": true, - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/cdk-assets/node_modules/jest-leak-detector": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", - "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-mock/node_modules/@types/node": { - "version": "22.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", - "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-mock/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } - } - }, - "node_modules/cdk-assets/node_modules/jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-resolve": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", - "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-resolve-dependencies": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", - "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-runner": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/environment": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-leak-detector": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-resolve": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-util": "^29.7.0", - "jest-watcher": "^29.7.0", - "jest-worker": "^29.7.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-runner/node_modules/@types/node": { - "version": "22.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", - "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-runner/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/jest-runtime": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-runtime/node_modules/@types/node": { - "version": "22.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", - "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-runtime/node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/jest-runtime/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/jest-snapshot": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-util/node_modules/@types/node": { - "version": "22.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", - "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-util/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/jest-watcher": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-watcher/node_modules/@types/node": { - "version": "22.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", - "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-watcher/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-worker/node_modules/@types/node": { - "version": "22.13.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.1.tgz", - "integrity": "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/cdk-assets/node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/cdk-assets/node_modules/jest-worker/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/cdk-assets/node_modules/jsdom": { - "version": "25.0.1", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", - "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "cssstyle": "^4.1.0", - "data-urls": "^5.0.0", - "decimal.js": "^10.4.3", - "form-data": "^4.0.0", - "html-encoding-sniffer": "^4.0.0", - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.5", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.12", - "parse5": "^7.1.2", - "rrweb-cssom": "^0.7.1", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^5.0.0", - "w3c-xmlserializer": "^5.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^3.1.1", - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.0.0", - "ws": "^8.18.0", - "xml-name-validator": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "canvas": "^2.11.2" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/cdk-assets/node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "extraneous": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "extraneous": true, - "license": "ISC" - }, - "node_modules/cdk-assets/node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "extraneous": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/cdk-assets/node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", - "engines": [ - "node >= 0.2.0" - ], - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/jsonschema": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz", - "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/cdk-assets/node_modules/JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "extraneous": true, - "license": "(MIT OR Apache-2.0)", - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/cdk-assets/node_modules/jszip": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", - "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", - "extraneous": true, - "license": "(MIT OR GPL-3.0-or-later)", - "dependencies": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "setimmediate": "^1.0.5" - } - }, - "node_modules/cdk-assets/node_modules/jszip/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/jszip/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/cdk-assets/node_modules/jszip/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/cdk-assets/node_modules/just-extend": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", - "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/cdk-assets/node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/lazystream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", - "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "^2.0.5" - }, - "engines": { - "node": ">= 0.6.3" - } - }, - "node_modules/cdk-assets/node_modules/lazystream/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/lazystream/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/cdk-assets/node_modules/lazystream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/cdk-assets/node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/cdk-assets/node_modules/lie": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", - "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "immediate": "~3.0.5" - } - }, - "node_modules/cdk-assets/node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/load-json-file/node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/lodash.difference": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", - "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", - "dev": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", - "dev": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/lodash.ismatch": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", - "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "dev": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/lodash.union": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", - "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/loupe": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", - "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "extraneous": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cdk-assets/node_modules/madge": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/madge/-/madge-8.0.0.tgz", - "integrity": "sha512-9sSsi3TBPhmkTCIpVQF0SPiChj1L7Rq9kU2KDG1o6v2XH9cCw086MopjVCD+vuoL5v8S77DTbVopTO8OUiQpIw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "commander": "^7.2.0", - "commondir": "^1.0.1", - "debug": "^4.3.4", - "dependency-tree": "^11.0.0", - "ora": "^5.4.1", - "pluralize": "^8.0.0", - "pretty-ms": "^7.0.1", - "rc": "^1.2.8", - "stream-to-array": "^2.3.0", - "ts-graphviz": "^2.1.2", - "walkdir": "^0.4.1" - }, - "bin": { - "madge": "bin/cli.js" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "individual", - "url": "https://www.paypal.me/pahen" - }, - "peerDependencies": { - "typescript": "^5.4.4" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/cdk-assets/node_modules/madge/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/cdk-assets/node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, - "node_modules/cdk-assets/node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "extraneous": true, - "license": "ISC" - }, - "node_modules/cdk-assets/node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "extraneous": true, - "license": "BSD-3-Clause", - "dependencies": { - "tmpl": "1.0.5" - } - }, - "node_modules/cdk-assets/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/cdk-assets/node_modules/meow": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", - "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/meow/node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "extraneous": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cdk-assets/node_modules/meow/node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/meow/node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/meow/node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "extraneous": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/meow/node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "extraneous": true, - "license": "ISC" - }, - "node_modules/cdk-assets/node_modules/meow/node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "extraneous": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/cdk-assets/node_modules/meow/node_modules/read-pkg/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "extraneous": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/cdk-assets/node_modules/meow/node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "extraneous": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/cdk-assets/node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/cdk-assets/node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true, - "license": "MIT", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/cdk-assets/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cdk-assets/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cdk-assets/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/minimatch": { - "version": "3.1.2", - "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" - }, - "engines": { - "node": "*" - } - }, - "node_modules/cdk-assets/node_modules/minimatch/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==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/cdk-assets/node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "extraneous": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/cdk-assets/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "extraneous": true, - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cdk-assets/node_modules/modify-values": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", - "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/node_modules/module-definition": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/module-definition/-/module-definition-6.0.1.tgz", - "integrity": "sha512-FeVc50FTfVVQnolk/WQT8MX+2WVcDnTGiq6Wo+/+lJ2ET1bRVi3HG3YlJUfqagNMc/kUlFSoR96AJkxGpKz13g==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "ast-module-types": "^6.0.1", - "node-source-walk": "^7.0.1" - }, - "bin": { - "module-definition": "bin/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/module-lookup-amd": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/module-lookup-amd/-/module-lookup-amd-9.0.4.tgz", - "integrity": "sha512-DWJEuLVvjxh5b8wrvJC5wr2a7qo7pOWXIgdCBNazU416kcIyzO4drxvlqKhsHzYwxcC4cWuhoK+MiWCKCGnv7A==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "commander": "^12.1.0", - "glob": "^7.2.3", - "requirejs": "^2.3.7", - "requirejs-config-file": "^4.0.0" - }, - "bin": { - "lookup-amd": "bin/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", - "extraneous": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/cdk-assets/node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/nise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/nise/-/nise-6.1.1.tgz", - "integrity": "sha512-aMSAzLVY7LyeM60gvBS423nBmIPP+Wy7St7hsb+8/fc1HmeoHJfLO8CKse4u3BtOZvQLJghYPI2i/1WZrEj5/g==", - "extraneous": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "^13.0.1", - "@sinonjs/text-encoding": "^0.7.3", - "just-extend": "^6.2.0", - "path-to-regexp": "^8.1.0" - } - }, - "node_modules/cdk-assets/node_modules/nise/node_modules/@sinonjs/fake-timers": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", - "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", - "extraneous": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1" - } - }, - "node_modules/cdk-assets/node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/node-source-walk": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/node-source-walk/-/node-source-walk-7.0.1.tgz", - "integrity": "sha512-3VW/8JpPqPvnJvseXowjZcirPisssnBuDikk6JIZ8jQzF7KJQX52iPFX4RYYxLycYH7IbMRSPUOga/esVjy5Yg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.26.7" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "extraneous": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/cdk-assets/node_modules/normalize-package-data/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "extraneous": true, - "license": "ISC" - }, - "node_modules/cdk-assets/node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "extraneous": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/cdk-assets/node_modules/normalize-path": { - "version": "3.0.0", - "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" - } - }, - "node_modules/cdk-assets/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/nwsapi": { - "version": "2.2.16", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.16.tgz", - "integrity": "sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/cdk-assets/node_modules/object.assign": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", - "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0", - "has-symbols": "^1.1.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/object.groupby": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/cdk-assets/node_modules/object.values": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", - "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/cdk-assets/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/cdk-assets/node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/own-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", - "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.6", - "object-keys": "^1.1.1", - "safe-push-apply": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/p-locate/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "extraneous": true, - "license": "(MIT AND Zlib)" - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/parse-ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz", - "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/parse5": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", - "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "entities": "^4.5.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/cdk-assets/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/path-to-regexp": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", - "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=16" - } - }, - "node_modules/cdk-assets/node_modules/path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/pathval": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", - "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 14.16" - } - }, - "node_modules/cdk-assets/node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "extraneous": true, - "license": "ISC" - }, - "node_modules/cdk-assets/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/cdk-assets/node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/cdk-assets/node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/cdk-assets/node_modules/postcss": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", - "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==", - "extraneous": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.8", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/cdk-assets/node_modules/postcss-values-parser": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-6.0.2.tgz", - "integrity": "sha512-YLJpK0N1brcNJrs9WatuJFtHaV9q5aAOj+S4DI5S7jgHlRfm0PIbDCAFRYMQD5SHq7Fy6xsDhyutgS0QOAs0qw==", - "extraneous": true, - "license": "MPL-2.0", - "dependencies": { - "color-name": "^1.1.4", - "is-url-superb": "^4.0.0", - "quote-unquote": "^1.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "postcss": "^8.2.9" - } - }, - "node_modules/cdk-assets/node_modules/precinct": { - "version": "12.1.3", - "resolved": "https://registry.npmjs.org/precinct/-/precinct-12.1.3.tgz", - "integrity": "sha512-6zuVmMR89TGHQ0oI2632SjTrqqnhoTkB/AuxQchWNmv5BJXFdUEG86rq7geI41/hX7hGadMJ5em6eQWwpSHK7A==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@dependents/detective-less": "^5.0.1", - "commander": "^12.1.0", - "detective-amd": "^6.0.1", - "detective-cjs": "^6.0.1", - "detective-es6": "^5.0.1", - "detective-postcss": "^7.0.1", - "detective-sass": "^6.0.1", - "detective-scss": "^5.0.1", - "detective-stylus": "^5.0.1", - "detective-typescript": "^13.0.1", - "detective-vue2": "^2.1.2", - "module-definition": "^6.0.1", - "node-source-walk": "^7.0.1", - "postcss": "^8.5.1", - "typescript": "^5.7.3" - }, - "bin": { - "precinct": "bin/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/cdk-assets/node_modules/prettier": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", - "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", - "extraneous": true, - "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/cdk-assets/node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/cdk-assets/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cdk-assets/node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/cdk-assets/node_modules/pretty-ms": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz", - "integrity": "sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "parse-ms": "^2.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/projen": { - "version": "0.91.8", - "resolved": "https://registry.npmjs.org/projen/-/projen-0.91.8.tgz", - "integrity": "sha512-TWpxSiv3ZkJoZ2Y0hjnjwmKLlUnxmbPANmQ8yDdUeE6LIYoPmfU0Zw0ijNDI3uTq0BjIz5mFDkic94RW/1Hguw==", - "bundleDependencies": [ - "@iarna/toml", - "case", - "chalk", - "comment-json", - "conventional-changelog-config-spec", - "fast-json-patch", - "glob", - "ini", - "semver", - "shx", - "xmlbuilder2", - "yaml", - "yargs" - ], - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "@iarna/toml": "^2.2.5", - "case": "^1.6.3", - "chalk": "^4.1.2", - "comment-json": "4.2.2", - "constructs": "^10.0.0", - "conventional-changelog-config-spec": "^2.1.0", - "fast-json-patch": "^3.1.1", - "glob": "^8", - "ini": "^2.0.0", - "semver": "^7.7.1", - "shx": "^0.3.4", - "xmlbuilder2": "^3.1.1", - "yaml": "^2.2.2", - "yargs": "^17.7.2" - }, - "bin": { - "projen": "bin/projen" - }, - "engines": { - "node": ">= 16.0.0" - }, - "peerDependencies": { - "constructs": "^10.0.0" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/@iarna/toml": { - "version": "2.2.5", - "extraneous": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/@oozcitak/dom": { - "version": "1.15.10", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "@oozcitak/infra": "1.0.8", - "@oozcitak/url": "1.0.4", - "@oozcitak/util": "8.3.8" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/@oozcitak/infra": { - "version": "1.0.8", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "@oozcitak/util": "8.3.8" - }, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/@oozcitak/url": { - "version": "1.0.4", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "@oozcitak/infra": "1.0.8", - "@oozcitak/util": "8.3.8" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/@oozcitak/util": { - "version": "8.3.8", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8.0" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/ansi-regex": { - "version": "5.0.1", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/ansi-styles": { - "version": "4.3.0", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/argparse": { - "version": "1.0.10", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/array-timsort": { - "version": "1.0.3", - "extraneous": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/balanced-match": { - "version": "1.0.2", - "extraneous": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/brace-expansion": { - "version": "2.0.1", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/case": { - "version": "1.6.3", - "extraneous": true, - "inBundle": true, - "license": "(MIT OR GPL-3.0-or-later)", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/chalk": { - "version": "4.1.2", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/cliui": { - "version": "8.0.1", - "extraneous": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/color-convert": { - "version": "2.0.1", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/color-name": { - "version": "1.1.4", - "extraneous": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/comment-json": { - "version": "4.2.2", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "array-timsort": "^1.0.3", - "core-util-is": "^1.0.3", - "esprima": "^4.0.1", - "has-own-prop": "^2.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/concat-map": { - "version": "0.0.1", - "extraneous": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/conventional-changelog-config-spec": { - "version": "2.1.0", - "extraneous": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/core-util-is": { - "version": "1.0.3", - "extraneous": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/emoji-regex": { - "version": "8.0.0", - "extraneous": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/escalade": { - "version": "3.2.0", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/esprima": { - "version": "4.0.1", - "extraneous": true, - "inBundle": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/fast-json-patch": { - "version": "3.1.1", - "extraneous": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/fs.realpath": { - "version": "1.0.0", - "extraneous": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/function-bind": { - "version": "1.1.2", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/get-caller-file": { - "version": "2.0.5", - "extraneous": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/glob": { - "version": "8.1.0", - "extraneous": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/glob/node_modules/minimatch": { - "version": "5.1.6", - "extraneous": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/has-flag": { - "version": "4.0.0", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/has-own-prop": { - "version": "2.0.0", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/hasown": { - "version": "2.0.2", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/inflight": { - "version": "1.0.6", - "extraneous": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/inherits": { - "version": "2.0.4", - "extraneous": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/ini": { - "version": "2.0.0", - "extraneous": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/interpret": { - "version": "1.4.0", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/is-core-module": { - "version": "2.16.1", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/js-yaml": { - "version": "3.14.1", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/minimatch": { - "version": "3.1.2", - "extraneous": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/minimatch/node_modules/brace-expansion": { - "version": "1.1.11", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/minimist": { - "version": "1.2.8", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/once": { - "version": "1.4.0", - "extraneous": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/path-is-absolute": { - "version": "1.0.1", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/path-parse": { - "version": "1.0.7", - "extraneous": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/rechoir": { - "version": "0.6.2", - "extraneous": true, - "inBundle": true, - "dependencies": { - "resolve": "^1.1.6" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/repeat-string": { - "version": "1.6.1", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/require-directory": { - "version": "2.1.1", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/resolve": { - "version": "1.22.10", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/semver": { - "version": "7.7.1", - "extraneous": true, - "inBundle": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/shelljs": { - "version": "0.8.5", - "extraneous": true, - "inBundle": true, - "license": "BSD-3-Clause", - "dependencies": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - }, - "bin": { - "shjs": "bin/shjs" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/shelljs/node_modules/glob": { - "version": "7.2.3", - "extraneous": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/shx": { - "version": "0.3.4", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.3", - "shelljs": "^0.8.5" - }, - "bin": { - "shx": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/sprintf-js": { - "version": "1.0.3", - "extraneous": true, - "inBundle": true, - "license": "BSD-3-Clause" - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/string-width": { - "version": "4.2.3", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/strip-ansi": { - "version": "6.0.1", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/supports-color": { - "version": "7.2.0", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/wrap-ansi": { - "version": "7.0.0", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/wrappy": { - "version": "1.0.2", - "extraneous": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/xmlbuilder2": { - "version": "3.1.1", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "@oozcitak/dom": "1.15.10", - "@oozcitak/infra": "1.0.8", - "@oozcitak/util": "8.3.8", - "js-yaml": "3.14.1" - }, - "engines": { - "node": ">=12.0" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/y18n": { - "version": "5.0.8", - "extraneous": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/yaml": { - "version": "2.7.0", - "extraneous": true, - "inBundle": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/yargs": { - "version": "17.7.2", - "extraneous": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "extraneous": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/cdk-assets/node_modules/projen/node_modules/yargs/node_modules/yargs-parser": { - "version": "21.1.1", - "extraneous": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/cdk-assets/node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/cdk-assets/node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/pure-rand": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", - "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", - "extraneous": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "extraneous": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/quote-unquote": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/quote-unquote/-/quote-unquote-1.0.0.tgz", - "integrity": "sha512-twwRO/ilhlG/FIgYeKGFqyHhoEhqgnKVkcmqMKi2r524gz3ZbDTcyFt38E9xjJI2vT+KbRNHVbnJ/e0I25Azwg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "extraneous": true, - "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/cdk-assets/node_modules/rc/node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/read-pkg-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "integrity": "sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "find-up": "^2.0.0", - "read-pkg": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/read-pkg-up/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/read-pkg-up/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/read-pkg-up/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/read-pkg-up/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/read-pkg-up/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/cdk-assets/node_modules/readdir-glob": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", - "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "minimatch": "^5.1.0" - } - }, - "node_modules/cdk-assets/node_modules/readdir-glob/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cdk-assets/node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", - "extraneous": true, - "dependencies": { - "resolve": "^1.1.6" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/cdk-assets/node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/reflect.getprototypeof": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", - "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.1", - "which-builtin-type": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/cdk-assets/node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/node_modules/requirejs": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.7.tgz", - "integrity": "sha512-DouTG8T1WanGok6Qjg2SXuCMzszOo0eHeH9hDZ5Y4x8Je+9JB38HdTLT4/VA8OaUhBa0JPVHJ0pyBkM1z+pDsw==", - "extraneous": true, - "license": "MIT", - "bin": { - "r_js": "bin/r.js", - "r.js": "bin/r.js" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/cdk-assets/node_modules/requirejs-config-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/requirejs-config-file/-/requirejs-config-file-4.0.0.tgz", - "integrity": "sha512-jnIre8cbWOyvr8a5F2KuqBnY+SDA4NXr/hzEZJG79Mxm2WiFQz2dzhC8ibtPJS7zkmBEl1mxSwp5HhC1W4qpxw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "esprima": "^4.0.0", - "stringify-object": "^3.2.1" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/cdk-assets/node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/resolve-dependency-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/resolve-dependency-path/-/resolve-dependency-path-4.0.1.tgz", - "integrity": "sha512-YQftIIC4vzO9UMhO/sCgXukNyiwVRCVaxiWskCBy7Zpqkplm8kTAISZ8O1MoKW1ca6xzgLUBjZTcDgypXvXxiQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "extraneous": true, - "license": "MIT", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/cdk-assets/node_modules/resolve.exports": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", - "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/cdk-assets/node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "extraneous": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/node_modules/rrweb-cssom": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", - "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "extraneous": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/cdk-assets/node_modules/safe-array-concat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", - "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "has-symbols": "^1.1.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/safe-push-apply": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", - "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/safe-regex-test": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-regex": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/sass-lookup": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/sass-lookup/-/sass-lookup-6.1.0.tgz", - "integrity": "sha512-Zx+lVyoWqXZxHuYWlTA17Z5sczJ6braNT2C7rmClw+c4E7r/n911Zwss3h1uHI9reR5AgHZyNHF7c2+VIp5AUA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "commander": "^12.1.0", - "enhanced-resolve": "^5.18.0" - }, - "bin": { - "sass-lookup": "bin/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "extraneous": true, - "license": "ISC", - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=v12.22.7" - } - }, - "node_modules/cdk-assets/node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "extraneous": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/cdk-assets/node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/cdk-assets/node_modules/set-proto": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", - "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/cdk-assets/node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/shelljs": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", - "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", - "extraneous": true, - "license": "BSD-3-Clause", - "dependencies": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - }, - "bin": { - "shjs": "bin/shjs" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/shx": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/shx/-/shx-0.3.4.tgz", - "integrity": "sha512-N6A9MLVqjxZYcVn8hLmtneQWIJtp8IKzMP4eMnx+nqkvXoqinUPCbUFLp2UcWTEIUONhlk0ewxr/jaVGlc+J+g==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.3", - "shelljs": "^0.8.5" - }, - "bin": { - "shx": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "extraneous": true, - "license": "ISC" - }, - "node_modules/cdk-assets/node_modules/sinon": { - "version": "18.0.1", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-18.0.1.tgz", - "integrity": "sha512-a2N2TDY1uGviajJ6r4D1CyRAkzE9NNVlYOV1wX5xQDuAk0ONgzgRl0EjCQuRCPxOwp13ghsMwt9Gdldujs39qw==", - "extraneous": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "11.2.2", - "@sinonjs/samsam": "^8.0.0", - "diff": "^5.2.0", - "nise": "^6.0.0", - "supports-color": "^7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "node_modules/cdk-assets/node_modules/sinon/node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", - "extraneous": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/cdk-assets/node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "extraneous": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/node_modules/source-map-js": { - "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==", - "extraneous": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/node_modules/source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/cdk-assets/node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "extraneous": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/cdk-assets/node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "extraneous": true, - "license": "CC-BY-3.0" - }, - "node_modules/cdk-assets/node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/cdk-assets/node_modules/spdx-license-ids": { - "version": "3.0.21", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz", - "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==", - "extraneous": true, - "license": "CC0-1.0" - }, - "node_modules/cdk-assets/node_modules/split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/cdk-assets/node_modules/split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "extraneous": true, - "license": "ISC", - "dependencies": { - "readable-stream": "^3.0.0" - } - }, - "node_modules/cdk-assets/node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "extraneous": true, - "license": "BSD-3-Clause" - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cdk-assets/node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/stream-browserify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", - "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "~2.0.4", - "readable-stream": "^3.5.0" - } - }, - "node_modules/cdk-assets/node_modules/stream-to-array": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/stream-to-array/-/stream-to-array-2.3.0.tgz", - "integrity": "sha512-UsZtOYEn4tWU2RGLOXr/o/xjRBftZRlG3dEWoaHr8j4GuypJ3isitGbVyjQKAuMu+xbiop8q224TjiZWc4XTZA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.1.0" - } - }, - "node_modules/cdk-assets/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/cdk-assets/node_modules/string_decoder/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cdk-assets/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", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/string.prototype.trim": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", - "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-data-property": "^1.1.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-object-atoms": "^1.0.0", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/string.prototype.trimend": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", - "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/stringify-object": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", - "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", - "extraneous": true, - "license": "BSD-2-Clause", - "dependencies": { - "get-own-enumerable-property-symbols": "^3.0.0", - "is-obj": "^1.0.1", - "is-regexp": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/stringify-object/node_modules/is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cdk-assets/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" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/cdk-assets/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cdk-assets/node_modules/strnum": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", - "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", - "dev": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/stylus-lookup": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/stylus-lookup/-/stylus-lookup-6.1.0.tgz", - "integrity": "sha512-5QSwgxAzXPMN+yugy61C60PhoANdItfdjSEZR8siFwz7yL9jTmV0UBKDCfn3K8GkGB4g0Y9py7vTCX8rFu4/pQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "commander": "^12.1.0" - }, - "bin": { - "stylus-lookup": "bin/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/cdk-assets/node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/synckit": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", - "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/cdk-assets/node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "extraneous": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/text-extensions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", - "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/cdk-assets/node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/cdk-assets/node_modules/through2/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/through2/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/cdk-assets/node_modules/through2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/archiver-utils/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" } }, - "node_modules/cdk-assets/node_modules/tinyrainbow": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", - "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/cdk-assets/node_modules/tinyspy": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", - "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/cdk-assets/node_modules/tldts": { - "version": "6.1.76", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.76.tgz", - "integrity": "sha512-6U2ti64/nppsDxQs9hw8ephA3nO6nSQvVVfxwRw8wLQPFtLI1cFI1a1eP22g+LUP+1TA2pKKjUTwWB+K2coqmQ==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "tldts-core": "^6.1.76" - }, - "bin": { - "tldts": "bin/cli.js" - } - }, - "node_modules/cdk-assets/node_modules/tldts-core": { - "version": "6.1.76", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.76.tgz", - "integrity": "sha512-uzhJ02RaMzgQR3yPoeE65DrcHI6LoM4saUqXOt/b5hmb3+mc4YWpdSeAQqVqRUlQ14q8ZuLRWyBR1ictK1dzzg==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, "license": "MIT" }, - "node_modules/cdk-assets/node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "extraneous": true, - "license": "BSD-3-Clause" - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } + "node_modules/cdk-assets/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" }, - "node_modules/cdk-assets/node_modules/tough-cookie": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.0.tgz", - "integrity": "sha512-rvZUv+7MoBYTiDmFPBrhL7Ujx9Sk+q9wwm22x8c8T5IJaR+Wsyc7TNxbVxo84kZoRJZZMazowFLqpankBEQrGg==", - "extraneous": true, - "license": "BSD-3-Clause", - "dependencies": { - "tldts": "^6.1.32" - }, - "engines": { - "node": ">=16" - } + "node_modules/cdk-assets/node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" }, - "node_modules/cdk-assets/node_modules/tr46": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", - "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, "license": "MIT", "dependencies": { - "punycode": "^2.3.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cdk-assets/node_modules/ts-api-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz", - "integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" } }, - "node_modules/cdk-assets/node_modules/ts-graphviz": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/ts-graphviz/-/ts-graphviz-2.1.6.tgz", - "integrity": "sha512-XyLVuhBVvdJTJr2FJJV2L1pc4MwSjMhcunRVgDE9k4wbb2ee7ORYnPewxMWUav12vxyfUM686MSGsqnVRIInuw==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/bl/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, "funding": [ { "type": "github", - "url": "https://github.com/sponsors/ts-graphviz" + "url": "https://github.com/sponsors/feross" }, { - "type": "opencollective", - "url": "https://opencollective.com/ts-graphviz" + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } ], "license": "MIT", "dependencies": { - "@ts-graphviz/adapter": "^2.0.6", - "@ts-graphviz/ast": "^2.0.7", - "@ts-graphviz/common": "^2.1.5", - "@ts-graphviz/core": "^2.0.7" - }, - "engines": { - "node": ">=18" + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, - "node_modules/cdk-assets/node_modules/ts-jest": { - "version": "29.2.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.5.tgz", - "integrity": "sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/bowser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/cdk-assets/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==", + "dev": true, "license": "MIT", "dependencies": { - "bs-logger": "^0.2.6", - "ejs": "^3.1.10", - "fast-json-stable-stringify": "^2.1.0", - "jest-util": "^29.0.0", - "json5": "^2.2.3", - "lodash.memoize": "^4.1.2", - "make-error": "^1.3.6", - "semver": "^7.6.3", - "yargs-parser": "^21.1.1" - }, - "bin": { - "ts-jest": "cli.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/transform": "^29.0.0", - "@jest/types": "^29.0.0", - "babel-jest": "^29.0.0", - "jest": "^29.0.0", - "typescript": ">=4.3 <6" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@jest/transform": { - "optional": true - }, - "@jest/types": { - "optional": true - }, - "babel-jest": { - "optional": true - }, - "esbuild": { - "optional": true - } + "balanced-match": "^1.0.0" } }, - "node_modules/cdk-assets/node_modules/ts-jest/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "extraneous": true, - "license": "ISC", - "engines": { - "node": ">=12" + "node_modules/cdk-assets/node_modules/buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "dev": true, + "license": "MIT", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" } }, - "node_modules/cdk-assets/node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, "license": "MIT", - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } + "engines": { + "node": "*" } }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "license": "ISC", "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" } }, - "node_modules/cdk-assets/node_modules/tsconfig-paths/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==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "license": "MIT", "dependencies": { - "minimist": "^1.2.0" + "color-name": "~1.1.4" }, - "bin": { - "json5": "lib/cli.js" + "engines": { + "node": ">=7.0.0" } }, - "node_modules/cdk-assets/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==", + "node_modules/cdk-assets/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, - "license": "0BSD" + "license": "MIT" }, - "node_modules/cdk-assets/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==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/compress-commons": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz", + "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", + "dev": true, "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1" + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 10" } }, - "node_modules/cdk-assets/node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=4" - } + "node_modules/cdk-assets/node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" }, - "node_modules/cdk-assets/node_modules/type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "extraneous": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" + "node_modules/cdk-assets/node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cdk-assets/node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=0.8" } }, - "node_modules/cdk-assets/node_modules/typed-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/crc32-stream": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz", + "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", + "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" }, "engines": { - "node": ">= 0.4" + "node": ">= 10" } }, - "node_modules/cdk-assets/node_modules/typed-array-byte-length": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", - "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/emoji-regex": { + "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, + "license": "MIT" + }, + "node_modules/cdk-assets/node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.14" - }, + "once": "^1.4.0" + } + }, + "node_modules/cdk-assets/node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=6" } }, - "node_modules/cdk-assets/node_modules/typed-array-byte-offset": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", - "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/cdk-assets/node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.15", - "reflect.getprototypeof": "^1.0.9" + "strnum": "^1.0.5" }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/cdk-assets/node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true, + "license": "MIT" + }, + "node_modules/cdk-assets/node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/cdk-assets/node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/cdk-assets/node_modules/typed-array-length": { - "version": "1.0.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==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "license": "ISC", "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0", - "reflect.getprototypeof": "^1.0.6" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">= 0.4" + "node": "*" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/cdk-assets/node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "extraneous": true, - "license": "MIT" + "node_modules/cdk-assets/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, + "license": "ISC" }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" + "node_modules/cdk-assets/node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/cdk-assets/node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/cdk-assets/node_modules/uglify-js": { - "version": "3.19.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", - "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", - "extraneous": true, - "license": "BSD-2-Clause", - "bin": { - "uglifyjs": "bin/uglifyjs" - }, + "node_modules/cdk-assets/node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/cdk-assets/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "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": ">=0.8.0" + "node": ">=8" } }, - "node_modules/cdk-assets/node_modules/unbox-primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", - "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "has-bigints": "^1.0.2", - "has-symbols": "^1.1.0", - "which-boxed-primitive": "^1.1.1" + "readable-stream": "^2.0.5" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.6.3" } }, - "node_modules/cdk-assets/node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/lazystream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, "license": "MIT" }, - "node_modules/cdk-assets/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, "license": "MIT", - "engines": { - "node": ">= 10.0.0" + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/cdk-assets/node_modules/update-browserslist-db": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", - "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", - "extraneous": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], + "node_modules/cdk-assets/node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, "license": "MIT", "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" + "safe-buffer": "~5.1.0" } }, - "node_modules/cdk-assets/node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "extraneous": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } + "node_modules/cdk-assets/node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "dev": true, + "license": "MIT" }, - "node_modules/cdk-assets/node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "node_modules/cdk-assets/node_modules/lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", "dev": true, "license": "MIT" }, - "node_modules/cdk-assets/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "node_modules/cdk-assets/node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", "dev": true, - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } + "license": "MIT" }, - "node_modules/cdk-assets/node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, "license": "MIT" }, - "node_modules/cdk-assets/node_modules/v8-to-istanbul": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", - "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", - "extraneous": true, - "license": "ISC", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" + "node_modules/cdk-assets/node_modules/lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/cdk-assets/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" }, "engines": { - "node": ">=10.12.0" + "node": ">=4.0.0" } }, - "node_modules/cdk-assets/node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "extraneous": true, - "license": "Apache-2.0", + "node_modules/cdk-assets/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "node_modules/cdk-assets/node_modules/w3c-xmlserializer": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", - "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/minimatch/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==", + "dev": true, "license": "MIT", "dependencies": { - "xml-name-validator": "^5.0.0" - }, - "engines": { - "node": ">=18" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/cdk-assets/node_modules/walkdir": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.4.1.tgz", - "integrity": "sha512-3eBwRyEln6E1MSzcxcVpQIhRG8Q1jLvEqRmCZqS3dsfXEDR/AhOF4d+jHg1qvDCpYaVRZjENPQyrVxAkQqxPgQ==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, "license": "MIT", "engines": { - "node": ">=6.0.0" + "node": ">=0.10.0" } }, - "node_modules/cdk-assets/node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "extraneous": true, - "license": "Apache-2.0", + "node_modules/cdk-assets/node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", "dependencies": { - "makeerror": "1.0.12" + "wrappy": "1" } }, - "node_modules/cdk-assets/node_modules/wcwidth": { + "node_modules/cdk-assets/node_modules/path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "extraneous": true, + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, "license": "MIT", - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/cdk-assets/node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "extraneous": true, - "license": "BSD-2-Clause", "engines": { - "node": ">=12" + "node": ">=0.10.0" } }, - "node_modules/cdk-assets/node_modules/whatwg-encoding": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", - "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/cdk-assets/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, "license": "MIT", "dependencies": { - "iconv-lite": "0.6.3" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, "engines": { - "node": ">=18" + "node": ">= 6" } }, - "node_modules/cdk-assets/node_modules/whatwg-mimetype": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", - "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", - "extraneous": true, - "license": "MIT", + "node_modules/cdk-assets/node_modules/readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/cdk-assets/node_modules/readdir-glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": ">=18" + "node": ">=10" } }, - "node_modules/cdk-assets/node_modules/whatwg-url": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.1.0.tgz", - "integrity": "sha512-jlf/foYIKywAt3x/XWKZ/3rz8OSJPiWktjmk891alJUEjiVxKX9LEO92qH3hv4aJ0mN3MWPvGMCy8jQi95xK4w==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, "license": "MIT", - "dependencies": { - "tr46": "^5.0.0", - "webidl-conversions": "^7.0.0" - }, "engines": { - "node": ">=18" + "node": ">=0.10.0" } }, - "node_modules/cdk-assets/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "extraneous": true, - "license": "ISC", + "node_modules/cdk-assets/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/cdk-assets/node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dev": true, + "license": "MIT", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" } }, - "node_modules/cdk-assets/node_modules/which-boxed-primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", - "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, "license": "MIT", "dependencies": { - "is-bigint": "^1.1.0", - "is-boolean-object": "^1.2.1", - "is-number-object": "^1.1.1", - "is-string": "^1.1.1", - "is-symbol": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "safe-buffer": "~5.2.0" } }, - "node_modules/cdk-assets/node_modules/which-builtin-type": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", - "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/cdk-assets/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": { - "call-bound": "^1.0.2", - "function.prototype.name": "^1.1.6", - "has-tostringtag": "^1.0.2", - "is-async-function": "^2.0.0", - "is-date-object": "^1.1.0", - "is-finalizationregistry": "^1.1.0", - "is-generator-function": "^1.0.10", - "is-regex": "^1.2.1", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.1.0", - "which-collection": "^1.0.2", - "which-typed-array": "^1.1.16" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/cdk-assets/node_modules/which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", - "extraneous": true, + "node_modules/cdk-assets/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": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/cdk-assets/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==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "dev": true, + "license": "MIT" + }, + "node_modules/cdk-assets/node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "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", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2" + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=6" } }, - "node_modules/cdk-assets/node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } + "node_modules/cdk-assets/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==", + "dev": true, + "license": "0BSD" }, - "node_modules/cdk-assets/node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "extraneous": true, + "node_modules/cdk-assets/node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, "license": "MIT" }, + "node_modules/cdk-assets/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/cdk-assets/node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -36572,92 +24617,6 @@ "dev": true, "license": "ISC" }, - "node_modules/cdk-assets/node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "extraneous": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/cdk-assets/node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/cdk-assets/node_modules/xml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/xml-name-validator": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", - "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", - "extraneous": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/cdk-assets/node_modules/xmlbuilder2": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/xmlbuilder2/-/xmlbuilder2-3.1.1.tgz", - "integrity": "sha512-WCSfbfZnQDdLQLiMdGUQpMxxckeQ4oZNMNhLVkcekTu7xhD4tuUDyAPoY8CwXvBYE6LwBHd6QW2WZXlOWr1vCw==", - "extraneous": true, - "license": "MIT", - "dependencies": { - "@oozcitak/dom": "1.15.10", - "@oozcitak/infra": "1.0.8", - "@oozcitak/util": "8.3.8", - "js-yaml": "3.14.1" - }, - "engines": { - "node": ">=12.0" - } - }, - "node_modules/cdk-assets/node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "extraneous": true, - "license": "MIT" - }, - "node_modules/cdk-assets/node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=0.4" - } - }, "node_modules/cdk-assets/node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -36668,26 +24627,6 @@ "node": ">=10" } }, - "node_modules/cdk-assets/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "extraneous": true, - "license": "ISC" - }, - "node_modules/cdk-assets/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==", - "extraneous": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/cdk-assets/node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", @@ -36717,29 +24656,6 @@ "node": ">=10" } }, - "node_modules/cdk-assets/node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cdk-assets/node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "extraneous": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/cdk-assets/node_modules/zip-stream": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", diff --git a/src/pricing-service/package.json b/src/pricing-service/package.json index 54c1844d..e1824c83 100644 --- a/src/pricing-service/package.json +++ b/src/pricing-service/package.json @@ -47,7 +47,7 @@ "dependencies": { "@aws-lambda-powertools/logger": "^2.20.0", "@aws-lambda-powertools/parameters": "^2.20.0", - "@types/jsonwebtoken": "^9.0.9", + "@types/jsonwebtoken": "^9.0.10", "cloudevents": "^9.0.0", "jsonwebtoken": "^9.0.2", "zod": "^3.25.49"