From f03436b210ac1dc41cf3fab55b9850d7ff06505d Mon Sep 17 00:00:00 2001 From: Matthew Warman Date: Fri, 19 Dec 2025 06:09:44 -0500 Subject: [PATCH 1/9] Refactor API Gateway response handling and update dependencies to use @leanstacks/lambda-utils --- package-lock.json | 13 ++- package.json | 3 +- src/handlers/create-task.ts | 26 ++--- src/handlers/delete-task.ts | 22 ++-- src/handlers/get-task.ts | 22 ++-- src/handlers/list-tasks.ts | 18 +-- src/handlers/update-task.ts | 30 ++--- src/services/task-service.ts | 2 +- src/utils/apigateway-response.test.ts | 153 -------------------------- src/utils/apigateway-response.ts | 27 ----- src/utils/constants.test.ts | 60 ++++++++++ src/utils/constants.ts | 9 ++ src/utils/dynamodb-client.ts | 4 +- src/utils/logger.ts | 24 ++-- src/utils/sns-client.ts | 4 +- 15 files changed, 140 insertions(+), 277 deletions(-) delete mode 100644 src/utils/apigateway-response.test.ts delete mode 100644 src/utils/apigateway-response.ts create mode 100644 src/utils/constants.test.ts create mode 100644 src/utils/constants.ts diff --git a/package-lock.json b/package-lock.json index 21f6e34..efb710c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,8 +13,7 @@ "@aws-sdk/client-lambda": "3.953.0", "@aws-sdk/client-sns": "3.953.0", "@aws-sdk/lib-dynamodb": "3.953.0", - "pino": "10.1.0", - "pino-lambda": "4.4.1", + "@leanstacks/lambda-utils": "0.2.0-alpha.3", "zod": "4.2.1" }, "devDependencies": { @@ -2275,6 +2274,16 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@leanstacks/lambda-utils": { + "version": "0.2.0-alpha.3", + "resolved": "https://registry.npmjs.org/@leanstacks/lambda-utils/-/lambda-utils-0.2.0-alpha.3.tgz", + "integrity": "sha512-ZFCvUgzdqxzfQLepbg44GCLNI64BokoA6a4pjhQvLoFZeIxsOQo/oZCetu6XPde67D5eDcKyUgBHtveS3KW+4A==", + "license": "MIT", + "dependencies": { + "pino": "10.1.0", + "pino-lambda": "4.4.1" + } + }, "node_modules/@napi-rs/wasm-runtime": { "version": "0.2.12", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", diff --git a/package.json b/package.json index e2a3703..c721579 100644 --- a/package.json +++ b/package.json @@ -58,8 +58,7 @@ "@aws-sdk/client-lambda": "3.953.0", "@aws-sdk/client-sns": "3.953.0", "@aws-sdk/lib-dynamodb": "3.953.0", - "pino": "10.1.0", - "pino-lambda": "4.4.1", + "@leanstacks/lambda-utils": "0.2.0-alpha.3", "zod": "4.2.1" } } diff --git a/src/handlers/create-task.ts b/src/handlers/create-task.ts index fb5ebd0..e70dde6 100644 --- a/src/handlers/create-task.ts +++ b/src/handlers/create-task.ts @@ -1,17 +1,11 @@ import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda'; -import { lambdaRequestTracker } from 'pino-lambda'; import { ZodError } from 'zod'; +import { badRequest, created, internalServerError, withRequestTracking } from '@leanstacks/lambda-utils'; -import { CreateTaskDtoSchema } from '@/models/create-task-dto.js'; -import { createTask } from '@/services/task-service.js'; -import { badRequest, created, internalServerError } from '@/utils/apigateway-response.js'; -import { logger } from '@/utils/logger.js'; - -/** - * Lambda request tracker middleware for logging. - * @see https://www.npmjs.com/package/pino-lambda#best-practices - */ -const withRequestTracking = lambdaRequestTracker(); +import { defaultResponseHeaders } from '@/utils/constants'; +import { CreateTaskDtoSchema } from '@/models/create-task-dto'; +import { createTask } from '@/services/task-service'; +import { logger } from '@/utils/logger'; /** * Lambda handler for creating a new task @@ -28,7 +22,7 @@ export const handler = async (event: APIGatewayProxyEvent, context: Context): Pr // Parse and validate request body if (!event.body) { logger.warn('[CreateTaskHandler] < handler - missing request body'); - return badRequest('Request body is required'); + return badRequest('Request body is required', defaultResponseHeaders); } let requestBody: unknown; @@ -36,7 +30,7 @@ export const handler = async (event: APIGatewayProxyEvent, context: Context): Pr requestBody = JSON.parse(event.body); } catch (_error) { logger.warn('[CreateTaskHandler] < handler - invalid JSON in request body'); - return badRequest('Invalid JSON in request body'); + return badRequest('Invalid JSON in request body', defaultResponseHeaders); } // Validate request body against schema @@ -52,7 +46,7 @@ export const handler = async (event: APIGatewayProxyEvent, context: Context): Pr '[CreateTaskHandler] < handler - successfully created task', ); // Return created response with the new task - return created(task); + return created(task, defaultResponseHeaders); } catch (error) { if (error instanceof ZodError) { // Handle validation errors @@ -63,11 +57,11 @@ export const handler = async (event: APIGatewayProxyEvent, context: Context): Pr }, '[CreateTaskHandler] < handler - validation error', ); - return badRequest(`Validation failed: ${errorMessages}`); + return badRequest(`Validation failed: ${errorMessages}`, defaultResponseHeaders); } // Handle other errors logger.error({ error }, '[CreateTaskHandler] < handler - failed to create task'); - return internalServerError('Failed to create task'); + return internalServerError('Failed to create task', defaultResponseHeaders); } }; diff --git a/src/handlers/delete-task.ts b/src/handlers/delete-task.ts index 37f005f..9b702b0 100644 --- a/src/handlers/delete-task.ts +++ b/src/handlers/delete-task.ts @@ -1,15 +1,9 @@ import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda'; -import { lambdaRequestTracker } from 'pino-lambda'; +import { internalServerError, noContent, notFound, withRequestTracking } from '@leanstacks/lambda-utils'; -import { deleteTask } from '@/services/task-service.js'; -import { internalServerError, noContent, notFound } from '@/utils/apigateway-response.js'; -import { logger } from '@/utils/logger.js'; - -/** - * Lambda request tracker middleware for logging. - * @see https://www.npmjs.com/package/pino-lambda#best-practices - */ -const withRequestTracking = lambdaRequestTracker(); +import { defaultResponseHeaders } from '@/utils/constants'; +import { deleteTask } from '@/services/task-service'; +import { logger } from '@/utils/logger'; /** * Lambda handler for deleting a task by ID @@ -28,7 +22,7 @@ export const handler = async (event: APIGatewayProxyEvent, context: Context): Pr if (!taskId) { logger.warn('[DeleteTaskHandler] < handler - missing taskId path parameter'); - return notFound('Task not found'); + return notFound('Task not found', defaultResponseHeaders); } // Delete the task @@ -37,15 +31,15 @@ export const handler = async (event: APIGatewayProxyEvent, context: Context): Pr // Check if the task was found and deleted if (!deleted) { logger.info({ taskId }, '[DeleteTaskHandler] < handler - task not found'); - return notFound('Task not found'); + return notFound('Task not found', defaultResponseHeaders); } // Return no content response logger.info({ taskId }, '[DeleteTaskHandler] < handler - successfully deleted task'); - return noContent(); + return noContent(defaultResponseHeaders); } catch (error) { // Handle unexpected errors logger.error({ error }, '[DeleteTaskHandler] < handler - failed to delete task'); - return internalServerError('Failed to delete task'); + return internalServerError('Failed to delete task', defaultResponseHeaders); } }; diff --git a/src/handlers/get-task.ts b/src/handlers/get-task.ts index cb88292..04a894f 100644 --- a/src/handlers/get-task.ts +++ b/src/handlers/get-task.ts @@ -1,15 +1,9 @@ import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda'; -import { lambdaRequestTracker } from 'pino-lambda'; +import { internalServerError, notFound, ok, withRequestTracking } from '@leanstacks/lambda-utils'; -import { getTask } from '@/services/task-service.js'; -import { internalServerError, notFound, ok } from '@/utils/apigateway-response.js'; -import { logger } from '@/utils/logger.js'; - -/** - * Lambda request tracker middleware for logging. - * @see https://www.npmjs.com/package/pino-lambda#best-practices - */ -const withRequestTracking = lambdaRequestTracker(); +import { defaultResponseHeaders } from '@/utils/constants'; +import { getTask } from '@/services/task-service'; +import { logger } from '@/utils/logger'; /** * Lambda handler for retrieving a task by ID @@ -28,7 +22,7 @@ export const handler = async (event: APIGatewayProxyEvent, context: Context): Pr if (!taskId) { logger.warn('[GetTaskHandler] < handler - missing taskId path parameter'); - return notFound('Task not found'); + return notFound('Task not found', defaultResponseHeaders); } // Retrieve the task @@ -37,15 +31,15 @@ export const handler = async (event: APIGatewayProxyEvent, context: Context): Pr // Check if the task was found if (!task) { logger.info({ taskId }, '[GetTaskHandler] < handler - task not found'); - return notFound('Task not found'); + return notFound('Task not found', defaultResponseHeaders); } // Return ok response with the task logger.info({ taskId }, '[GetTaskHandler] < handler - successfully retrieved task'); - return ok(task); + return ok(task, defaultResponseHeaders); } catch (error) { // Handle unexpected errors logger.error({ error }, '[GetTaskHandler] < handler - failed to get task'); - return internalServerError('Failed to retrieve task'); + return internalServerError('Failed to retrieve task', defaultResponseHeaders); } }; diff --git a/src/handlers/list-tasks.ts b/src/handlers/list-tasks.ts index 81a7463..ede03c5 100644 --- a/src/handlers/list-tasks.ts +++ b/src/handlers/list-tasks.ts @@ -1,15 +1,9 @@ import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda'; -import { lambdaRequestTracker } from 'pino-lambda'; +import { withRequestTracking, internalServerError, ok } from '@leanstacks/lambda-utils'; -import { listTasks } from '@/services/task-service.js'; -import { internalServerError, ok } from '@/utils/apigateway-response.js'; -import { logger } from '@/utils/logger.js'; - -/** - * Lambda request tracker middleware for logging. - * @see https://www.npmjs.com/package/pino-lambda#best-practices - */ -const withRequestTracking = lambdaRequestTracker(); +import { logger } from '@/utils/logger'; +import { defaultResponseHeaders } from '@/utils/constants'; +import { listTasks } from '@/services/task-service'; /** * Lambda handler for listing all tasks @@ -28,10 +22,10 @@ export const handler = async (event: APIGatewayProxyEvent, context: Context): Pr // Return ok response with the list of tasks logger.info({ count: tasks.length }, '[ListTasksHandler] < handler - successfully retrieved tasks'); - return ok(tasks); + return ok(tasks, defaultResponseHeaders); } catch (error) { // Handle unexpected errors logger.error({ error }, '[ListTasksHandler] < handler - failed to list tasks'); - return internalServerError('Failed to retrieve tasks'); + return internalServerError('Failed to retrieve tasks', defaultResponseHeaders); } }; diff --git a/src/handlers/update-task.ts b/src/handlers/update-task.ts index f4f33f4..8a8f0d5 100644 --- a/src/handlers/update-task.ts +++ b/src/handlers/update-task.ts @@ -1,17 +1,11 @@ import { APIGatewayProxyEvent, APIGatewayProxyResult, Context } from 'aws-lambda'; -import { lambdaRequestTracker } from 'pino-lambda'; import { ZodError } from 'zod'; +import { badRequest, internalServerError, notFound, ok, withRequestTracking } from '@leanstacks/lambda-utils'; -import { UpdateTaskDtoSchema } from '@/models/update-task-dto.js'; -import { updateTask } from '@/services/task-service.js'; -import { badRequest, internalServerError, notFound, ok } from '@/utils/apigateway-response.js'; -import { logger } from '@/utils/logger.js'; - -/** - * Lambda request tracker middleware for logging. - * @see https://www.npmjs.com/package/pino-lambda#best-practices - */ -const withRequestTracking = lambdaRequestTracker(); +import { defaultResponseHeaders } from '@/utils/constants'; +import { UpdateTaskDtoSchema } from '@/models/update-task-dto'; +import { updateTask } from '@/services/task-service'; +import { logger } from '@/utils/logger'; /** * Lambda handler for updating an existing task @@ -29,13 +23,13 @@ export const handler = async (event: APIGatewayProxyEvent, context: Context): Pr const taskId = event.pathParameters?.taskId; if (!taskId) { logger.warn('[UpdateTaskHandler] < handler - missing taskId'); - return badRequest('Task ID is required'); + return badRequest('Task ID is required', defaultResponseHeaders); } // Parse and validate request body if (!event.body) { logger.warn('[UpdateTaskHandler] < handler - missing request body'); - return badRequest('Request body is required'); + return badRequest('Request body is required', defaultResponseHeaders); } let requestBody: unknown; @@ -43,7 +37,7 @@ export const handler = async (event: APIGatewayProxyEvent, context: Context): Pr requestBody = JSON.parse(event.body); } catch (_error) { logger.warn('[UpdateTaskHandler] < handler - invalid JSON in request body'); - return badRequest('Invalid JSON in request body'); + return badRequest('Invalid JSON in request body', defaultResponseHeaders); } // Validate request body against schema @@ -55,22 +49,22 @@ export const handler = async (event: APIGatewayProxyEvent, context: Context): Pr // Check if the task was found if (!task) { logger.info({ taskId }, '[UpdateTaskHandler] < handler - task not found'); - return notFound(); + return notFound('Task not found', defaultResponseHeaders); } // Return ok response with the updated task logger.info({ id: task.id }, '[UpdateTaskHandler] < handler - successfully updated task'); - return ok(task); + return ok(task, defaultResponseHeaders); } catch (error) { // Handle validation errors if (error instanceof ZodError) { const errorMessages = error.issues.map((err) => `${err.path.join('.')}: ${err.message}`).join(', '); logger.warn({ issues: error.issues }, '[UpdateTaskHandler] < handler - validation error'); - return badRequest(`Validation failed: ${errorMessages}`); + return badRequest(`Validation failed: ${errorMessages}`, defaultResponseHeaders); } // Handle other unexpected errors logger.error({ error }, '[UpdateTaskHandler] < handler - failed to update task'); - return internalServerError('Failed to update task'); + return internalServerError('Failed to update task', defaultResponseHeaders); } }; diff --git a/src/services/task-service.ts b/src/services/task-service.ts index 2b91aab..f79f761 100644 --- a/src/services/task-service.ts +++ b/src/services/task-service.ts @@ -5,8 +5,8 @@ import { CreateTaskDto } from '@/models/create-task-dto.js'; import { UpdateTaskDto } from '@/models/update-task-dto.js'; import { Task, TaskItem, TaskKeys, toTask } from '@/models/task.js'; import { config } from '@/utils/config.js'; +import { logger } from '@/utils/logger'; import { dynamoDocClient } from '@/utils/dynamodb-client.js'; -import { logger } from '@/utils/logger.js'; /** * Retrieves all tasks from the DynamoDB table diff --git a/src/utils/apigateway-response.test.ts b/src/utils/apigateway-response.test.ts deleted file mode 100644 index 2931360..0000000 --- a/src/utils/apigateway-response.test.ts +++ /dev/null @@ -1,153 +0,0 @@ -import { - createResponse, - ok, - created, - noContent, - badRequest, - notFound, - internalServerError, -} from './apigateway-response'; - -jest.mock('./config', () => ({ - config: { - CORS_ALLOW_ORIGIN: 'https://example.com', - TASKS_TABLE: 'mock-table', - }, -})); - -describe('apigateway-response', () => { - const corsOrigin = 'https://example.com'; - - beforeEach(() => { - // No setup needed for now, but placeholder for future cleanup/mocks - }); - - describe('createResponse', () => { - it('should return a valid API Gateway response with correct status and body', () => { - // Arrange - const status = 200; - const body = { foo: 'bar' }; - - // Act - const result = createResponse(status, body); - - // Assert - expect(result).toEqual({ - statusCode: status, - headers: { - 'Content-Type': 'application/json', - 'Access-Control-Allow-Origin': corsOrigin, - }, - body: JSON.stringify(body), - }); - }); - }); - - describe('ok', () => { - it('returns 200', () => { - // Arrange - const body = { hello: 'world' }; - - // Act - const result = ok(body); - - // Assert - expect(result.statusCode).toBe(200); - expect(result.body).toBe(JSON.stringify(body)); - }); - }); - - describe('created', () => { - it('returns 201', () => { - // Arrange - const body = { id: 1 }; - - // Act - const result = created(body); - - // Assert - expect(result.statusCode).toBe(201); - expect(result.body).toBe(JSON.stringify(body)); - }); - }); - - describe('noContent', () => { - it('returns 204 with empty object', () => { - // Act - const result = noContent(); - - // Assert - expect(result.statusCode).toBe(204); - expect(result.body).toBe(JSON.stringify({})); - }); - }); - - describe('badRequest', () => { - it('returns 400 with default message', () => { - // Act - const result = badRequest(); - - // Assert - expect(result.statusCode).toBe(400); - expect(JSON.parse(result.body)).toEqual({ message: 'Bad Request' }); - }); - - it('returns 400 with custom message', () => { - // Arrange - const message = 'Custom error'; - - // Act - const result = badRequest(message); - - // Assert - expect(result.statusCode).toBe(400); - expect(JSON.parse(result.body)).toEqual({ message }); - }); - }); - - describe('notFound', () => { - it('returns 404 with default message', () => { - // Act - const result = notFound(); - - // Assert - expect(result.statusCode).toBe(404); - expect(JSON.parse(result.body)).toEqual({ message: 'Not Found' }); - }); - - it('returns 404 with custom message', () => { - // Arrange - const message = 'Missing'; - - // Act - const result = notFound(message); - - // Assert - expect(result.statusCode).toBe(404); - expect(JSON.parse(result.body)).toEqual({ message }); - }); - }); - - describe('internalServerError', () => { - it('returns 500 with default message', () => { - // Act - const result = internalServerError(); - - // Assert - expect(result.statusCode).toBe(500); - expect(JSON.parse(result.body)).toEqual({ message: 'Internal Server Error' }); - }); - - it('returns 500 with custom message', () => { - // Arrange - const message = 'Oops'; - - // Act - const result = internalServerError(message); - - // Assert - expect(result.statusCode).toBe(500); - expect(JSON.parse(result.body)).toEqual({ message }); - }); - }); -}); diff --git a/src/utils/apigateway-response.ts b/src/utils/apigateway-response.ts deleted file mode 100644 index a2687cc..0000000 --- a/src/utils/apigateway-response.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { APIGatewayProxyResult } from 'aws-lambda'; - -import { config } from './config'; - -/** - * Creates a standardized API Gateway response with the given status code and body - * Includes CORS headers to allow cross-origin requests - */ -export const createResponse = (statusCode: number, body: unknown): APIGatewayProxyResult => { - return { - statusCode, - headers: { - 'Content-Type': 'application/json', - 'Access-Control-Allow-Origin': config.CORS_ALLOW_ORIGIN, - }, - body: JSON.stringify(body), - }; -}; - -// Common response patterns -export const ok = (body: unknown): APIGatewayProxyResult => createResponse(200, body); -export const created = (body: unknown): APIGatewayProxyResult => createResponse(201, body); -export const noContent = (): APIGatewayProxyResult => createResponse(204, {}); -export const badRequest = (message = 'Bad Request'): APIGatewayProxyResult => createResponse(400, { message }); -export const notFound = (message = 'Not Found'): APIGatewayProxyResult => createResponse(404, { message }); -export const internalServerError = (message = 'Internal Server Error'): APIGatewayProxyResult => - createResponse(500, { message }); diff --git a/src/utils/constants.test.ts b/src/utils/constants.test.ts new file mode 100644 index 0000000..a732257 --- /dev/null +++ b/src/utils/constants.test.ts @@ -0,0 +1,60 @@ +jest.mock('@leanstacks/lambda-utils', () => ({ + httpHeaders: { + cors: jest.fn(() => ({ 'Access-Control-Allow-Origin': 'https://example.com' })), + json: { 'Content-Type': 'application/json' }, + }, +})); +jest.mock('./config', () => ({ + config: { + CORS_ALLOW_ORIGIN: 'https://example.com', + }, +})); + +// Import after mocking +import { httpHeaders } from '@leanstacks/lambda-utils'; +import { defaultResponseHeaders } from './constants'; + +describe('constants', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('defaultResponseHeaders', () => { + it('should be defined', () => { + // Assert + expect(defaultResponseHeaders).toBeDefined(); + }); + + it('should be of type object', () => { + // Assert + expect(typeof defaultResponseHeaders).toBe('object'); + expect(defaultResponseHeaders).not.toBeNull(); + }); + + it('should include content-type header from jsonHeaders', () => { + // Assert + expect(defaultResponseHeaders).toHaveProperty('Content-Type'); + expect(defaultResponseHeaders['Content-Type']).toBe('application/json'); + }); + + it('should pass CORS_ALLOW_ORIGIN from config to corsHeaders', () => { + // The corsHeaders function is called during module initialization + // Verify it exists and is a mock function + expect(typeof httpHeaders.cors).toBe('function'); + expect((httpHeaders.cors as jest.Mock).mock).toBeDefined(); + }); + + it('should include CORS headers from corsHeaders function', () => { + // Assert + expect(defaultResponseHeaders).toHaveProperty('Access-Control-Allow-Origin'); + expect(defaultResponseHeaders['Access-Control-Allow-Origin']).toBe('https://example.com'); + }); + + it('should combine properties from both jsonHeaders and corsHeaders', () => { + // Assert - verify the object contains properties from both sources + expect(Object.keys(defaultResponseHeaders).length).toBeGreaterThanOrEqual(2); + expect(defaultResponseHeaders).toHaveProperty('Content-Type'); + expect(defaultResponseHeaders).toHaveProperty('Access-Control-Allow-Origin'); + }); + }); +}); diff --git a/src/utils/constants.ts b/src/utils/constants.ts new file mode 100644 index 0000000..93e3159 --- /dev/null +++ b/src/utils/constants.ts @@ -0,0 +1,9 @@ +import { httpHeaders, Headers } from '@leanstacks/lambda-utils'; + +import { config } from './config'; + +/** + * Default API response headers. + * Includes Content-Type and CORS headers. + */ +export const defaultResponseHeaders: Headers = { ...httpHeaders.json, ...httpHeaders.cors(config.CORS_ALLOW_ORIGIN) }; diff --git a/src/utils/dynamodb-client.ts b/src/utils/dynamodb-client.ts index 454084b..da61a86 100644 --- a/src/utils/dynamodb-client.ts +++ b/src/utils/dynamodb-client.ts @@ -1,8 +1,8 @@ import { DynamoDBClient, DynamoDBClientConfig } from '@aws-sdk/client-dynamodb'; import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb'; -import { config } from './config.js'; -import { logger } from './logger.js'; +import { config } from './config'; +import { logger } from './logger'; /** * Configuration for the DynamoDB client diff --git a/src/utils/logger.ts b/src/utils/logger.ts index d338eaf..34a8e00 100644 --- a/src/utils/logger.ts +++ b/src/utils/logger.ts @@ -1,23 +1,19 @@ -import pino from 'pino'; -import { CloudwatchLogFormatter, pinoLambdaDestination, StructuredLogFormatter } from 'pino-lambda'; +import { Logger } from '@leanstacks/lambda-utils'; import { config } from './config'; /** - * Initialize Pino Lambda destination - * @see https://www.npmjs.com/package/pino-lambda#best-practices + * Initializes and configures the logger instance with application settings. */ -const _lambdaDestination = pinoLambdaDestination({ - formatter: config.LOGGING_FORMAT === 'json' ? new StructuredLogFormatter() : new CloudwatchLogFormatter(), +const _logger = new Logger({ + enabled: config.LOGGING_ENABLED, + level: config.LOGGING_LEVEL, + format: config.LOGGING_FORMAT, }); /** - * Pino logger instance + * Exports the configured logger instance for use throughout the application. + * This singleton pattern promotes consistent logging behavior and prevents + * the creation of multiple logger instances, which can lead to performance issues. */ -export const logger = pino( - { - enabled: config.LOGGING_ENABLED, - level: config.LOGGING_LEVEL, - }, - _lambdaDestination, -); +export const logger = _logger.instance; diff --git a/src/utils/sns-client.ts b/src/utils/sns-client.ts index 0c0ee24..cba7a2a 100644 --- a/src/utils/sns-client.ts +++ b/src/utils/sns-client.ts @@ -1,7 +1,7 @@ import { MessageAttributeValue, PublishCommand, SNSClient } from '@aws-sdk/client-sns'; -import { config } from './config.js'; -import { logger } from './logger.js'; +import { config } from './config'; +import { logger } from './logger'; /** * SNS client instance for publishing messages to SNS topics. From 1a42863e8b7c61301698350c5e921d1f5a01229b Mon Sep 17 00:00:00 2001 From: Matthew Warman Date: Fri, 19 Dec 2025 10:28:06 -0500 Subject: [PATCH 2/9] Refactor DynamoDB client initialization to use @leanstacks/lambda-utils and update tests --- src/utils/dynamodb-client.test.ts | 121 +++++++++++++++++++----------- src/utils/dynamodb-client.ts | 37 +++++++-- 2 files changed, 109 insertions(+), 49 deletions(-) diff --git a/src/utils/dynamodb-client.test.ts b/src/utils/dynamodb-client.test.ts index b2e86c6..5d1c063 100644 --- a/src/utils/dynamodb-client.test.ts +++ b/src/utils/dynamodb-client.test.ts @@ -2,11 +2,36 @@ describe('dynamodb-client', () => { let dynamoDocClient: typeof import('./dynamodb-client').dynamoDocClient; let dynamoClient: typeof import('./dynamodb-client').dynamoClient; let mockLoggerInfo: jest.Mock; + let mockInitializeDynamoDBClients: jest.Mock; + let mockGetDynamoDBClient: jest.Mock; + let mockGetDynamoDBDocumentClient: jest.Mock; + let mockDynamoClient: any; + let mockDocClient: any; beforeEach(() => { // Reset modules to clear any cached imports jest.resetModules(); + // Create mock client instances + mockDynamoClient = { + constructor: { name: 'DynamoDBClient' }, + config: { region: 'us-east-1' }, + }; + mockDocClient = { + constructor: { name: 'DynamoDBDocumentClient' }, + }; + + // Mock the lambda-utils module + mockInitializeDynamoDBClients = jest.fn(); + mockGetDynamoDBClient = jest.fn().mockReturnValue(mockDynamoClient); + mockGetDynamoDBDocumentClient = jest.fn().mockReturnValue(mockDocClient); + + jest.doMock('@leanstacks/lambda-utils', () => ({ + initializeDynamoDBClients: mockInitializeDynamoDBClients, + getDynamoDBClient: mockGetDynamoDBClient, + getDynamoDBDocumentClient: mockGetDynamoDBDocumentClient, + })); + // Mock the config module jest.doMock('./config', () => ({ config: { @@ -36,37 +61,53 @@ describe('dynamodb-client', () => { }); describe('dynamoDBClient', () => { - it('should create a DynamoDB client instance', () => { + it('should initialize lambda-utils with correct configuration', () => { // Arrange & Act - const module = require('./dynamodb-client'); - dynamoClient = module.dynamoClient; + require('./dynamodb-client'); // Assert - expect(dynamoClient).toBeDefined(); - expect(dynamoClient.constructor.name).toBe('DynamoDBClient'); + expect(mockInitializeDynamoDBClients).toHaveBeenCalledWith( + { region: 'us-east-1' }, + { + convertEmptyValues: false, + convertClassInstanceToMap: true, + removeUndefinedValues: true, + }, + { + wrapNumbers: false, + }, + ); }); - it('should configure DynamoDB client with AWS region from config', () => { + it('should get DynamoDB client from lambda-utils', () => { // Arrange & Act const module = require('./dynamodb-client'); dynamoClient = module.dynamoClient; // Assert expect(dynamoClient).toBeDefined(); - // Verify the client has the config property - expect(dynamoClient.config).toBeDefined(); + expect(dynamoClient.constructor.name).toBe('DynamoDBClient'); + expect(mockGetDynamoDBClient).toHaveBeenCalled(); }); - it('should log initialization with region information', () => { + it('should log initialization with configuration information', () => { // Arrange & Act require('./dynamodb-client'); // Assert expect(mockLoggerInfo).toHaveBeenCalledWith( expect.objectContaining({ - dynamoDBClientConfig: expect.objectContaining({ + dynamoDbClientConfig: expect.objectContaining({ region: 'us-east-1', }), + marshallConfig: expect.objectContaining({ + convertEmptyValues: false, + convertClassInstanceToMap: true, + removeUndefinedValues: true, + }), + unmarshallConfig: expect.objectContaining({ + wrapNumbers: false, + }), }), '[DynamoDBClient] - Initialized AWS DynamoDB client', ); @@ -74,7 +115,7 @@ describe('dynamodb-client', () => { }); describe('dynamoDocClient', () => { - it('should create a DynamoDB Document client instance', () => { + it('should get DynamoDB Document client from lambda-utils', () => { // Arrange & Act const module = require('./dynamodb-client'); dynamoDocClient = module.dynamoDocClient; @@ -82,9 +123,10 @@ describe('dynamodb-client', () => { // Assert expect(dynamoDocClient).toBeDefined(); expect(dynamoDocClient.constructor.name).toBe('DynamoDBDocumentClient'); + expect(mockGetDynamoDBDocumentClient).toHaveBeenCalled(); }); - it('should create Document client from base DynamoDB client', () => { + it('should create Document client after DynamoDB client initialization', () => { // Arrange & Act const module = require('./dynamodb-client'); dynamoDocClient = module.dynamoDocClient; @@ -94,6 +136,7 @@ describe('dynamodb-client', () => { expect(dynamoDocClient).toBeDefined(); expect(dynamoClient).toBeDefined(); expect(dynamoDocClient.constructor.name).toBe('DynamoDBDocumentClient'); + expect(mockGetDynamoDBDocumentClient).toHaveBeenCalled(); }); }); @@ -104,44 +147,36 @@ describe('dynamodb-client', () => { const module2 = require('./dynamodb-client'); // Assert - same instances should be returned (singleton pattern) - expect(module1.dynamoDBClient).toBe(module2.dynamoDBClient); + expect(module1.dynamoClient).toBe(module2.dynamoClient); expect(module1.dynamoDocClient).toBe(module2.dynamoDocClient); - // Logger should only be called once during initialization - expect(mockLoggerInfo).toHaveBeenCalledTimes(1); + // initializeDynamoDBClients should only be called once during initialization + expect(mockInitializeDynamoDBClients).toHaveBeenCalledTimes(1); }); - it('should use different region when config changes', () => { - // Arrange - jest.resetModules(); - jest.doMock('./config', () => ({ - config: { - AWS_REGION: 'eu-west-1', - TASKS_TABLE: 'test-table', - LOGGING_ENABLED: true, - LOGGING_LEVEL: 'info', - CORS_ALLOW_ORIGIN: '*', - }, - })); - jest.doMock('./logger', () => ({ - logger: { - info: mockLoggerInfo, - debug: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - }, - })); + it('should pass correct configuration to initializeDynamoDBClients', () => { + // Arrange & Act + require('./dynamodb-client'); + + // Assert + const callArgs = mockInitializeDynamoDBClients.mock.calls[0]; + expect(callArgs[0]).toEqual({ region: 'us-east-1' }); + expect(callArgs[1]).toEqual({ + convertEmptyValues: false, + convertClassInstanceToMap: true, + removeUndefinedValues: true, + }); + expect(callArgs[2]).toEqual({ wrapNumbers: false }); + }); - // Act + it('should use AWS region from config', () => { + // Arrange & Act require('./dynamodb-client'); // Assert - expect(mockLoggerInfo).toHaveBeenCalledWith( - expect.objectContaining({ - dynamoDBClientConfig: expect.objectContaining({ - region: 'eu-west-1', - }), - }), - '[DynamoDBClient] - Initialized AWS DynamoDB client', + expect(mockInitializeDynamoDBClients).toHaveBeenCalledWith( + expect.objectContaining({ region: 'us-east-1' }), + expect.any(Object), + expect.any(Object), ); }); }); diff --git a/src/utils/dynamodb-client.ts b/src/utils/dynamodb-client.ts index da61a86..89f36ce 100644 --- a/src/utils/dynamodb-client.ts +++ b/src/utils/dynamodb-client.ts @@ -1,24 +1,49 @@ -import { DynamoDBClient, DynamoDBClientConfig } from '@aws-sdk/client-dynamodb'; +import { initializeDynamoDBClients, getDynamoDBClient, getDynamoDBDocumentClient } from '@leanstacks/lambda-utils'; +import { DynamoDBClient } from '@aws-sdk/client-dynamodb'; import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb'; import { config } from './config'; import { logger } from './logger'; /** - * Configuration for the DynamoDB client + * DynamoDB client configuration */ -const clientConfig: DynamoDBClientConfig = { +const dynamoDbClientConfig = { region: config.AWS_REGION, }; +/** + * Configuration for marshalling JavaScript objects into DynamoDB items + */ +const marshallConfig = { + convertEmptyValues: false, + convertClassInstanceToMap: true, + removeUndefinedValues: true, +}; + +/** + * Configuration for unmarshalling DynamoDB items into JavaScript objects + */ +const unmarshallConfig = { + wrapNumbers: false, +}; + +/** + * Initialize the DynamoDB clients with the microservice configuration. + */ +initializeDynamoDBClients(dynamoDbClientConfig, marshallConfig, unmarshallConfig); + /** * Singleton DynamoDB client configured with the application's region */ -export const dynamoClient = new DynamoDBClient(clientConfig); +export const dynamoClient: DynamoDBClient = getDynamoDBClient(); /** * Singleton DynamoDB Document client for easier interaction with DynamoDB */ -export const dynamoDocClient = DynamoDBDocumentClient.from(dynamoClient); +export const dynamoDocClient: DynamoDBDocumentClient = getDynamoDBDocumentClient(); -logger.info({ dynamoDBClientConfig: clientConfig }, '[DynamoDBClient] - Initialized AWS DynamoDB client'); +logger.info( + { dynamoDbClientConfig, marshallConfig, unmarshallConfig }, + '[DynamoDBClient] - Initialized AWS DynamoDB client', +); From f4c620cfe8481e812230c773420999dc7ccfdead Mon Sep 17 00:00:00 2001 From: Matthew Warman Date: Sat, 20 Dec 2025 05:52:29 -0500 Subject: [PATCH 3/9] chore: update AWS SDK and lambda-utils dependencies; refactor config tests and implementation - Updated AWS SDK dependencies to version 3.956.0. - Updated @leanstacks/lambda-utils to version 0.3.0-alpha.4. - Refactored config tests to simplify imports and remove unnecessary mocks. - Enhanced error handling in config validation to throw generic errors instead of specific messages. - Introduced createConfigManager from @leanstacks/lambda-utils for better config management. - Removed caching logic in favor of using the config manager for validation and refreshing. --- package-lock.json | 4385 ++++++++++++++++++++++++-------------- package.json | 10 +- src/utils/config.test.ts | 80 +- src/utils/config.ts | 40 +- 4 files changed, 2815 insertions(+), 1700 deletions(-) diff --git a/package-lock.json b/package-lock.json index efb710c..6eced19 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,11 +9,11 @@ "version": "0.2.0", "license": "MIT", "dependencies": { - "@aws-sdk/client-dynamodb": "3.953.0", - "@aws-sdk/client-lambda": "3.953.0", - "@aws-sdk/client-sns": "3.953.0", - "@aws-sdk/lib-dynamodb": "3.953.0", - "@leanstacks/lambda-utils": "0.2.0-alpha.3", + "@aws-sdk/client-dynamodb": "3.956.0", + "@aws-sdk/client-lambda": "3.956.0", + "@aws-sdk/client-sns": "3.956.0", + "@aws-sdk/lib-dynamodb": "3.956.0", + "@leanstacks/lambda-utils": "0.3.0-alpha.4", "zod": "4.2.1" }, "devDependencies": { @@ -175,570 +175,529 @@ } }, "node_modules/@aws-sdk/client-dynamodb": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.953.0.tgz", - "integrity": "sha512-QeSFxXgRjpr8M2wiLUsgg+mXEDtdhcuMnBWbXyjqUwca38pLEFJzJdFyOGul9RoQ2ICseuAy2/RZt0Ri1UgeZQ==", + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.956.0.tgz", + "integrity": "sha512-mM99L5f8Kg5IhdiZbp+WzJ1IYoxHQ/t9eEe29oh9xp7L7VafOQytJyKMVNOIsoiIRJT6XYtst5493G4JhcU4CQ==", "license": "Apache-2.0", "peer": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.953.0", - "@aws-sdk/credential-provider-node": "3.953.0", - "@aws-sdk/dynamodb-codec": "3.953.0", - "@aws-sdk/middleware-endpoint-discovery": "3.953.0", - "@aws-sdk/middleware-host-header": "3.953.0", - "@aws-sdk/middleware-logger": "3.953.0", - "@aws-sdk/middleware-recursion-detection": "3.953.0", - "@aws-sdk/middleware-user-agent": "3.953.0", - "@aws-sdk/region-config-resolver": "3.953.0", - "@aws-sdk/types": "3.953.0", - "@aws-sdk/util-endpoints": "3.953.0", - "@aws-sdk/util-user-agent-browser": "3.953.0", - "@aws-sdk/util-user-agent-node": "3.953.0", - "@smithy/config-resolver": "^4.4.4", - "@smithy/core": "^3.19.0", - "@smithy/fetch-http-handler": "^5.3.7", - "@smithy/hash-node": "^4.2.6", - "@smithy/invalid-dependency": "^4.2.6", - "@smithy/middleware-content-length": "^4.2.6", - "@smithy/middleware-endpoint": "^4.3.15", - "@smithy/middleware-retry": "^4.4.15", - "@smithy/middleware-serde": "^4.2.7", - "@smithy/middleware-stack": "^4.2.6", - "@smithy/node-config-provider": "^4.3.6", - "@smithy/node-http-handler": "^4.4.6", - "@smithy/protocol-http": "^5.3.6", - "@smithy/smithy-client": "^4.10.0", - "@smithy/types": "^4.10.0", - "@smithy/url-parser": "^4.2.6", + "@aws-sdk/core": "3.956.0", + "@aws-sdk/credential-provider-node": "3.956.0", + "@aws-sdk/dynamodb-codec": "3.956.0", + "@aws-sdk/middleware-endpoint-discovery": "3.956.0", + "@aws-sdk/middleware-host-header": "3.956.0", + "@aws-sdk/middleware-logger": "3.956.0", + "@aws-sdk/middleware-recursion-detection": "3.956.0", + "@aws-sdk/middleware-user-agent": "3.956.0", + "@aws-sdk/region-config-resolver": "3.956.0", + "@aws-sdk/types": "3.956.0", + "@aws-sdk/util-endpoints": "3.956.0", + "@aws-sdk/util-user-agent-browser": "3.956.0", + "@aws-sdk/util-user-agent-node": "3.956.0", + "@smithy/config-resolver": "^4.4.5", + "@smithy/core": "^3.20.0", + "@smithy/fetch-http-handler": "^5.3.8", + "@smithy/hash-node": "^4.2.7", + "@smithy/invalid-dependency": "^4.2.7", + "@smithy/middleware-content-length": "^4.2.7", + "@smithy/middleware-endpoint": "^4.4.1", + "@smithy/middleware-retry": "^4.4.17", + "@smithy/middleware-serde": "^4.2.8", + "@smithy/middleware-stack": "^4.2.7", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/node-http-handler": "^4.4.7", + "@smithy/protocol-http": "^5.3.7", + "@smithy/smithy-client": "^4.10.2", + "@smithy/types": "^4.11.0", + "@smithy/url-parser": "^4.2.7", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.14", - "@smithy/util-defaults-mode-node": "^4.2.17", - "@smithy/util-endpoints": "^3.2.6", - "@smithy/util-middleware": "^4.2.6", - "@smithy/util-retry": "^4.2.6", + "@smithy/util-defaults-mode-browser": "^4.3.16", + "@smithy/util-defaults-mode-node": "^4.2.19", + "@smithy/util-endpoints": "^3.2.7", + "@smithy/util-middleware": "^4.2.7", + "@smithy/util-retry": "^4.2.7", "@smithy/util-utf8": "^4.2.0", - "@smithy/util-waiter": "^4.2.6", + "@smithy/util-waiter": "^4.2.7", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-lambda": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.953.0.tgz", - "integrity": "sha512-Bsm5arLOjkrhGQzycmswnVWwJANd447h5e/TRqyYd07Zr6LIhylcACOeyJIoz7z1ffXTCTj8iLGE7Zac4g0mSQ==", + "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/middleware-endpoint-discovery": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.956.0.tgz", + "integrity": "sha512-p8oOhksZg3qxluKBM6J5F9Tv4cqzkjYYQO3iU3BENT3NXGvoHuaBbj6G/hXsKl1/jfGNUyIOpO+59r1L4zNqOg==", "license": "Apache-2.0", "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.953.0", - "@aws-sdk/credential-provider-node": "3.953.0", - "@aws-sdk/middleware-host-header": "3.953.0", - "@aws-sdk/middleware-logger": "3.953.0", - "@aws-sdk/middleware-recursion-detection": "3.953.0", - "@aws-sdk/middleware-user-agent": "3.953.0", - "@aws-sdk/region-config-resolver": "3.953.0", - "@aws-sdk/types": "3.953.0", - "@aws-sdk/util-endpoints": "3.953.0", - "@aws-sdk/util-user-agent-browser": "3.953.0", - "@aws-sdk/util-user-agent-node": "3.953.0", - "@smithy/config-resolver": "^4.4.4", - "@smithy/core": "^3.19.0", - "@smithy/eventstream-serde-browser": "^4.2.6", - "@smithy/eventstream-serde-config-resolver": "^4.3.6", - "@smithy/eventstream-serde-node": "^4.2.6", - "@smithy/fetch-http-handler": "^5.3.7", - "@smithy/hash-node": "^4.2.6", - "@smithy/invalid-dependency": "^4.2.6", - "@smithy/middleware-content-length": "^4.2.6", - "@smithy/middleware-endpoint": "^4.3.15", - "@smithy/middleware-retry": "^4.4.15", - "@smithy/middleware-serde": "^4.2.7", - "@smithy/middleware-stack": "^4.2.6", - "@smithy/node-config-provider": "^4.3.6", - "@smithy/node-http-handler": "^4.4.6", - "@smithy/protocol-http": "^5.3.6", - "@smithy/smithy-client": "^4.10.0", - "@smithy/types": "^4.10.0", - "@smithy/url-parser": "^4.2.6", - "@smithy/util-base64": "^4.3.0", - "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.14", - "@smithy/util-defaults-mode-node": "^4.2.17", - "@smithy/util-endpoints": "^3.2.6", - "@smithy/util-middleware": "^4.2.6", - "@smithy/util-retry": "^4.2.6", - "@smithy/util-stream": "^4.5.7", - "@smithy/util-utf8": "^4.2.0", - "@smithy/util-waiter": "^4.2.6", + "@aws-sdk/endpoint-cache": "3.953.0", + "@aws-sdk/types": "3.956.0", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/protocol-http": "^5.3.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-sns": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sns/-/client-sns-3.953.0.tgz", - "integrity": "sha512-tlmq3g9WxxMBZsOTak22gs8gXCXUCtKMZvl2CJrB6/kPm0CTqquKli/S7XmpWFj8BudUmf48R+Cc23AkRCvtPA==", + "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/middleware-host-header": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.956.0.tgz", + "integrity": "sha512-JujNJDp/dj1DbsI0ntzhrz2uJ4jpumcKtr743eMpEhdboYjuu/UzY8/7n1h5JbgU9TNXgqE9lgQNa5QPG0Tvsg==", "license": "Apache-2.0", "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.953.0", - "@aws-sdk/credential-provider-node": "3.953.0", - "@aws-sdk/middleware-host-header": "3.953.0", - "@aws-sdk/middleware-logger": "3.953.0", - "@aws-sdk/middleware-recursion-detection": "3.953.0", - "@aws-sdk/middleware-user-agent": "3.953.0", - "@aws-sdk/region-config-resolver": "3.953.0", - "@aws-sdk/types": "3.953.0", - "@aws-sdk/util-endpoints": "3.953.0", - "@aws-sdk/util-user-agent-browser": "3.953.0", - "@aws-sdk/util-user-agent-node": "3.953.0", - "@smithy/config-resolver": "^4.4.4", - "@smithy/core": "^3.19.0", - "@smithy/fetch-http-handler": "^5.3.7", - "@smithy/hash-node": "^4.2.6", - "@smithy/invalid-dependency": "^4.2.6", - "@smithy/middleware-content-length": "^4.2.6", - "@smithy/middleware-endpoint": "^4.3.15", - "@smithy/middleware-retry": "^4.4.15", - "@smithy/middleware-serde": "^4.2.7", - "@smithy/middleware-stack": "^4.2.6", - "@smithy/node-config-provider": "^4.3.6", - "@smithy/node-http-handler": "^4.4.6", - "@smithy/protocol-http": "^5.3.6", - "@smithy/smithy-client": "^4.10.0", - "@smithy/types": "^4.10.0", - "@smithy/url-parser": "^4.2.6", - "@smithy/util-base64": "^4.3.0", - "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.14", - "@smithy/util-defaults-mode-node": "^4.2.17", - "@smithy/util-endpoints": "^3.2.6", - "@smithy/util-middleware": "^4.2.6", - "@smithy/util-retry": "^4.2.6", - "@smithy/util-utf8": "^4.2.0", + "@aws-sdk/types": "3.956.0", + "@smithy/protocol-http": "^5.3.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-sso": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.953.0.tgz", - "integrity": "sha512-WU8XtORGnhy1JjTLflcGcNGU329pmwl/2claTVGp7vrgUKyreQV9Ke3BkMuUPYLOGO/Znstzc1VbUT9ORH3+WQ==", + "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/middleware-logger": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.956.0.tgz", + "integrity": "sha512-Qff39yEOPYgRsm4SrkHOvS0nSoxXILYnC8Akp0uMRi2lOcZVyXL3WCWqIOtI830qVI4GPa796sleKguxx50RHg==", "license": "Apache-2.0", "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.953.0", - "@aws-sdk/middleware-host-header": "3.953.0", - "@aws-sdk/middleware-logger": "3.953.0", - "@aws-sdk/middleware-recursion-detection": "3.953.0", - "@aws-sdk/middleware-user-agent": "3.953.0", - "@aws-sdk/region-config-resolver": "3.953.0", - "@aws-sdk/types": "3.953.0", - "@aws-sdk/util-endpoints": "3.953.0", - "@aws-sdk/util-user-agent-browser": "3.953.0", - "@aws-sdk/util-user-agent-node": "3.953.0", - "@smithy/config-resolver": "^4.4.4", - "@smithy/core": "^3.19.0", - "@smithy/fetch-http-handler": "^5.3.7", - "@smithy/hash-node": "^4.2.6", - "@smithy/invalid-dependency": "^4.2.6", - "@smithy/middleware-content-length": "^4.2.6", - "@smithy/middleware-endpoint": "^4.3.15", - "@smithy/middleware-retry": "^4.4.15", - "@smithy/middleware-serde": "^4.2.7", - "@smithy/middleware-stack": "^4.2.6", - "@smithy/node-config-provider": "^4.3.6", - "@smithy/node-http-handler": "^4.4.6", - "@smithy/protocol-http": "^5.3.6", - "@smithy/smithy-client": "^4.10.0", - "@smithy/types": "^4.10.0", - "@smithy/url-parser": "^4.2.6", - "@smithy/util-base64": "^4.3.0", - "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.14", - "@smithy/util-defaults-mode-node": "^4.2.17", - "@smithy/util-endpoints": "^3.2.6", - "@smithy/util-middleware": "^4.2.6", - "@smithy/util-retry": "^4.2.6", - "@smithy/util-utf8": "^4.2.0", + "@aws-sdk/types": "3.956.0", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/core": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.953.0.tgz", - "integrity": "sha512-hnz4ukn+XupuotZcFAyCIX41QqEWSHc8zf4gN4l5qVP2M8YCyZkLLZ5t5LaWLJkUFbOUU2w4SuGpUp+5ddtSkw==", + "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.956.0.tgz", + "integrity": "sha512-/f4JxL2kSCYhy63wovqts6SJkpalSLvuFe78ozt3ClrGoHGyr69o7tPRYx5U7azLgvrIGjsWUyTayeAk3YHIVQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.953.0", - "@aws-sdk/xml-builder": "3.953.0", - "@smithy/core": "^3.19.0", - "@smithy/node-config-provider": "^4.3.6", - "@smithy/property-provider": "^4.2.6", - "@smithy/protocol-http": "^5.3.6", - "@smithy/signature-v4": "^5.3.6", - "@smithy/smithy-client": "^4.10.0", - "@smithy/types": "^4.10.0", - "@smithy/util-base64": "^4.3.0", - "@smithy/util-middleware": "^4.2.6", - "@smithy/util-utf8": "^4.2.0", + "@aws-sdk/types": "3.956.0", + "@aws/lambda-invoke-store": "^0.2.2", + "@smithy/protocol-http": "^5.3.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.953.0.tgz", - "integrity": "sha512-ahOxDxvaKUf99LU9iRmRtPW2HLmsR+ix2WyzRGl1PpLltiRLMbKJHj5Tu2xyOsgLxs8tefK9D1j0SUgPk8GJ6g==", + "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/region-config-resolver": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.956.0.tgz", + "integrity": "sha512-byU5XYekW7+rZ3e067y038wlrpnPkdI4fMxcHCHrv+TAfzl8CCk5xLyzerQtXZR8cVPVOXuaYWe1zKW0uCnXUA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.953.0", - "@aws-sdk/types": "3.953.0", - "@smithy/property-provider": "^4.2.6", - "@smithy/types": "^4.10.0", + "@aws-sdk/types": "3.956.0", + "@smithy/config-resolver": "^4.4.5", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.953.0.tgz", - "integrity": "sha512-kYQEcJpJLiT+1ZdsQDMrIs2o3YydxdAIDdLUxbIwks1+WQz2sCr9b94ld19aMZ0rejosASO0J3dfY0lt3Tfl+Q==", + "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/types": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", + "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.953.0", - "@aws-sdk/types": "3.953.0", - "@smithy/fetch-http-handler": "^5.3.7", - "@smithy/node-http-handler": "^4.4.6", - "@smithy/property-provider": "^4.2.6", - "@smithy/protocol-http": "^5.3.6", - "@smithy/smithy-client": "^4.10.0", - "@smithy/types": "^4.10.0", - "@smithy/util-stream": "^4.5.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.953.0.tgz", - "integrity": "sha512-5cy6b3VntBvhRCanwohRtR0wbKKUd6JfIsnuXImB4JcZa2iMW5tDW0LhNangYZ9wrrM7sJol6cKHtUW9LNemFQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.953.0", - "@aws-sdk/credential-provider-env": "3.953.0", - "@aws-sdk/credential-provider-http": "3.953.0", - "@aws-sdk/credential-provider-login": "3.953.0", - "@aws-sdk/credential-provider-process": "3.953.0", - "@aws-sdk/credential-provider-sso": "3.953.0", - "@aws-sdk/credential-provider-web-identity": "3.953.0", - "@aws-sdk/nested-clients": "3.953.0", - "@aws-sdk/types": "3.953.0", - "@smithy/credential-provider-imds": "^4.2.6", - "@smithy/property-provider": "^4.2.6", - "@smithy/shared-ini-file-loader": "^4.4.1", - "@smithy/types": "^4.10.0", + "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/util-endpoints": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.956.0.tgz", + "integrity": "sha512-xZ5CBoubS4rs9JkFniKNShDtfqxaMUnwaebYMoybZm070q9+omFkQkJYXl7kopTViEgZgQl1sAsAkrawBM8qEQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.956.0", + "@smithy/types": "^4.11.0", + "@smithy/url-parser": "^4.2.7", + "@smithy/util-endpoints": "^3.2.7", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/credential-provider-login": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.953.0.tgz", - "integrity": "sha512-Drf4v7uBKnU/nY/qgQD9ZA2zD5gjQEatxQajQHUN54erDSQ2rB5ApNuTnc2cyNwaxURnQvO1J72mwO6P5lIpsg==", + "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.956.0.tgz", + "integrity": "sha512-s8KwYR3HqiGNni7a1DN2P3RUog64QoBQ6VCSzJkHBWb6++8KSOpqeeDkfmEz+22y1LOne+bRrpDGKa0aqOc3rQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.953.0", - "@aws-sdk/nested-clients": "3.953.0", - "@aws-sdk/types": "3.953.0", - "@smithy/property-provider": "^4.2.6", - "@smithy/protocol-http": "^5.3.6", - "@smithy/shared-ini-file-loader": "^4.4.1", - "@smithy/types": "^4.10.0", + "@aws-sdk/types": "3.956.0", + "@smithy/types": "^4.11.0", + "bowser": "^2.11.0", "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.953.0.tgz", - "integrity": "sha512-/3gUap/QwAV/U3RPStcSjdiksDboTdcz82qajfhURhtAe9iEdoKJy7vTYqg75eX7IjpgBwLGajt0URasUofrPg==", + "node_modules/@aws-sdk/client-lambda": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.956.0.tgz", + "integrity": "sha512-BiS7Z/rZA/1dquEzBJ/tNNpRuivOEv2bx4PVDbjiLXyaww/Rds+zkhP+0KdYPYWztKXT96CGRH7DCEiN9N4EEQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "3.953.0", - "@aws-sdk/credential-provider-http": "3.953.0", - "@aws-sdk/credential-provider-ini": "3.953.0", - "@aws-sdk/credential-provider-process": "3.953.0", - "@aws-sdk/credential-provider-sso": "3.953.0", - "@aws-sdk/credential-provider-web-identity": "3.953.0", - "@aws-sdk/types": "3.953.0", - "@smithy/credential-provider-imds": "^4.2.6", - "@smithy/property-provider": "^4.2.6", - "@smithy/shared-ini-file-loader": "^4.4.1", - "@smithy/types": "^4.10.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.956.0", + "@aws-sdk/credential-provider-node": "3.956.0", + "@aws-sdk/middleware-host-header": "3.956.0", + "@aws-sdk/middleware-logger": "3.956.0", + "@aws-sdk/middleware-recursion-detection": "3.956.0", + "@aws-sdk/middleware-user-agent": "3.956.0", + "@aws-sdk/region-config-resolver": "3.956.0", + "@aws-sdk/types": "3.956.0", + "@aws-sdk/util-endpoints": "3.956.0", + "@aws-sdk/util-user-agent-browser": "3.956.0", + "@aws-sdk/util-user-agent-node": "3.956.0", + "@smithy/config-resolver": "^4.4.5", + "@smithy/core": "^3.20.0", + "@smithy/eventstream-serde-browser": "^4.2.7", + "@smithy/eventstream-serde-config-resolver": "^4.3.7", + "@smithy/eventstream-serde-node": "^4.2.7", + "@smithy/fetch-http-handler": "^5.3.8", + "@smithy/hash-node": "^4.2.7", + "@smithy/invalid-dependency": "^4.2.7", + "@smithy/middleware-content-length": "^4.2.7", + "@smithy/middleware-endpoint": "^4.4.1", + "@smithy/middleware-retry": "^4.4.17", + "@smithy/middleware-serde": "^4.2.8", + "@smithy/middleware-stack": "^4.2.7", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/node-http-handler": "^4.4.7", + "@smithy/protocol-http": "^5.3.7", + "@smithy/smithy-client": "^4.10.2", + "@smithy/types": "^4.11.0", + "@smithy/url-parser": "^4.2.7", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.16", + "@smithy/util-defaults-mode-node": "^4.2.19", + "@smithy/util-endpoints": "^3.2.7", + "@smithy/util-middleware": "^4.2.7", + "@smithy/util-retry": "^4.2.7", + "@smithy/util-stream": "^4.5.8", + "@smithy/util-utf8": "^4.2.0", + "@smithy/util-waiter": "^4.2.7", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.953.0.tgz", - "integrity": "sha512-YeqzqxzBzXnqdzn4pBuoXeCmWrXOLIu5owAowUc4dOvHmtlpXxB3beJdQ9g/Ky6fG6iaAPKO1vrCEoHNjM85Dw==", + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/middleware-host-header": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.956.0.tgz", + "integrity": "sha512-JujNJDp/dj1DbsI0ntzhrz2uJ4jpumcKtr743eMpEhdboYjuu/UzY8/7n1h5JbgU9TNXgqE9lgQNa5QPG0Tvsg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.953.0", - "@aws-sdk/types": "3.953.0", - "@smithy/property-provider": "^4.2.6", - "@smithy/shared-ini-file-loader": "^4.4.1", - "@smithy/types": "^4.10.0", + "@aws-sdk/types": "3.956.0", + "@smithy/protocol-http": "^5.3.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.953.0.tgz", - "integrity": "sha512-Kp/49vAJweixMo3q85eVpq1JO9KgKc6A+f8/8WDkN5CkMsfKQcGJZbO5JtuJfzar4pPmRKbgOeOP1qQsOmfyfw==", + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/middleware-logger": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.956.0.tgz", + "integrity": "sha512-Qff39yEOPYgRsm4SrkHOvS0nSoxXILYnC8Akp0uMRi2lOcZVyXL3WCWqIOtI830qVI4GPa796sleKguxx50RHg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-sso": "3.953.0", - "@aws-sdk/core": "3.953.0", - "@aws-sdk/token-providers": "3.953.0", - "@aws-sdk/types": "3.953.0", - "@smithy/property-provider": "^4.2.6", - "@smithy/shared-ini-file-loader": "^4.4.1", - "@smithy/types": "^4.10.0", + "@aws-sdk/types": "3.956.0", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.953.0.tgz", - "integrity": "sha512-V8SpGVtNjQZboHjb/GLM4L3/6O/AZJFtwJ8fiBaemKMTntl8haioZlQHDklWixR9s9zthOdFsCDs1+92ndUBRw==", + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.956.0.tgz", + "integrity": "sha512-/f4JxL2kSCYhy63wovqts6SJkpalSLvuFe78ozt3ClrGoHGyr69o7tPRYx5U7azLgvrIGjsWUyTayeAk3YHIVQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.953.0", - "@aws-sdk/nested-clients": "3.953.0", - "@aws-sdk/types": "3.953.0", - "@smithy/property-provider": "^4.2.6", - "@smithy/shared-ini-file-loader": "^4.4.1", - "@smithy/types": "^4.10.0", + "@aws-sdk/types": "3.956.0", + "@aws/lambda-invoke-store": "^0.2.2", + "@smithy/protocol-http": "^5.3.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/dynamodb-codec": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/dynamodb-codec/-/dynamodb-codec-3.953.0.tgz", - "integrity": "sha512-VJDM2VvFb/VQxiRXmLw4sWCDqhAuYNzD5toANgwRazeZmCg0em6dtLdb97Q+4BT+MBXI4t1CS2xKaGtKOieNug==", + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/region-config-resolver": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.956.0.tgz", + "integrity": "sha512-byU5XYekW7+rZ3e067y038wlrpnPkdI4fMxcHCHrv+TAfzl8CCk5xLyzerQtXZR8cVPVOXuaYWe1zKW0uCnXUA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.953.0", - "@smithy/core": "^3.19.0", - "@smithy/smithy-client": "^4.10.0", - "@smithy/types": "^4.10.0", - "@smithy/util-base64": "^4.3.0", + "@aws-sdk/types": "3.956.0", + "@smithy/config-resolver": "^4.4.5", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-dynamodb": "^3.953.0" } }, - "node_modules/@aws-sdk/endpoint-cache": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.953.0.tgz", - "integrity": "sha512-pz67DoHk5WNmvMuyNDiomUS2xo0mq6Z3TdfLJZlWVbSKi3h8hYxVQchJ2kzgTr6wu6zt3UBbtKV9yY1IBhKMVA==", + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/types": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", + "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", "license": "Apache-2.0", "dependencies": { - "mnemonist": "0.38.3", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/lib-dynamodb": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.953.0.tgz", - "integrity": "sha512-oiCj2gZumRjhnv2RfI3oYgx0TFeollUt5JEzWjcCFbT2Ou9J2Ay1FEH9/xYGLxHu/NCGUVEAHdwuDsJcb09KHQ==", + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/util-endpoints": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.956.0.tgz", + "integrity": "sha512-xZ5CBoubS4rs9JkFniKNShDtfqxaMUnwaebYMoybZm070q9+omFkQkJYXl7kopTViEgZgQl1sAsAkrawBM8qEQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.953.0", - "@aws-sdk/util-dynamodb": "3.953.0", - "@smithy/core": "^3.19.0", - "@smithy/smithy-client": "^4.10.0", - "@smithy/types": "^4.10.0", + "@aws-sdk/types": "3.956.0", + "@smithy/types": "^4.11.0", + "@smithy/url-parser": "^4.2.7", + "@smithy/util-endpoints": "^3.2.7", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-dynamodb": "^3.953.0" } }, - "node_modules/@aws-sdk/middleware-endpoint-discovery": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.953.0.tgz", - "integrity": "sha512-/YKB1/OiWr7TwOfmkqzv8x1xgOpU71yciQTfsq6erB3dTQhdukPADt/CMJOhWFKC6Q1D5cDN8381nsGmnNuBVg==", + "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.956.0.tgz", + "integrity": "sha512-s8KwYR3HqiGNni7a1DN2P3RUog64QoBQ6VCSzJkHBWb6++8KSOpqeeDkfmEz+22y1LOne+bRrpDGKa0aqOc3rQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/endpoint-cache": "3.953.0", - "@aws-sdk/types": "3.953.0", - "@smithy/node-config-provider": "^4.3.6", - "@smithy/protocol-http": "^5.3.6", - "@smithy/types": "^4.10.0", + "@aws-sdk/types": "3.956.0", + "@smithy/types": "^4.11.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-sns": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sns/-/client-sns-3.956.0.tgz", + "integrity": "sha512-xd9bPtTaLid0y68HGK8m/C9Ig6tUrGsqmKzXOLj/LXKdK38XVeJcGB765F2JGMZ+JhjrTpz/w3QykMGiWMgoVA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.956.0", + "@aws-sdk/credential-provider-node": "3.956.0", + "@aws-sdk/middleware-host-header": "3.956.0", + "@aws-sdk/middleware-logger": "3.956.0", + "@aws-sdk/middleware-recursion-detection": "3.956.0", + "@aws-sdk/middleware-user-agent": "3.956.0", + "@aws-sdk/region-config-resolver": "3.956.0", + "@aws-sdk/types": "3.956.0", + "@aws-sdk/util-endpoints": "3.956.0", + "@aws-sdk/util-user-agent-browser": "3.956.0", + "@aws-sdk/util-user-agent-node": "3.956.0", + "@smithy/config-resolver": "^4.4.5", + "@smithy/core": "^3.20.0", + "@smithy/fetch-http-handler": "^5.3.8", + "@smithy/hash-node": "^4.2.7", + "@smithy/invalid-dependency": "^4.2.7", + "@smithy/middleware-content-length": "^4.2.7", + "@smithy/middleware-endpoint": "^4.4.1", + "@smithy/middleware-retry": "^4.4.17", + "@smithy/middleware-serde": "^4.2.8", + "@smithy/middleware-stack": "^4.2.7", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/node-http-handler": "^4.4.7", + "@smithy/protocol-http": "^5.3.7", + "@smithy/smithy-client": "^4.10.2", + "@smithy/types": "^4.11.0", + "@smithy/url-parser": "^4.2.7", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.16", + "@smithy/util-defaults-mode-node": "^4.2.19", + "@smithy/util-endpoints": "^3.2.7", + "@smithy/util-middleware": "^4.2.7", + "@smithy/util-retry": "^4.2.7", + "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.953.0.tgz", - "integrity": "sha512-jTGhfkONav+r4E6HLOrl5SzBqDmPByUYCkyB/c/3TVb8jX3wAZx8/q9bphKpCh+G5ARi3IdbSisgkZrJYqQ19Q==", + "node_modules/@aws-sdk/client-sns/node_modules/@aws-sdk/middleware-host-header": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.956.0.tgz", + "integrity": "sha512-JujNJDp/dj1DbsI0ntzhrz2uJ4jpumcKtr743eMpEhdboYjuu/UzY8/7n1h5JbgU9TNXgqE9lgQNa5QPG0Tvsg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.953.0", - "@smithy/protocol-http": "^5.3.6", - "@smithy/types": "^4.10.0", + "@aws-sdk/types": "3.956.0", + "@smithy/protocol-http": "^5.3.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/middleware-logger": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.953.0.tgz", - "integrity": "sha512-PlWdVYgcuptkIC0ZKqVUhWNtSHXJSx7U9V8J7dJjRmsXC40X7zpEycvrkzDMJjeTDGcCceYbyYAg/4X1lkcIMw==", + "node_modules/@aws-sdk/client-sns/node_modules/@aws-sdk/middleware-logger": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.956.0.tgz", + "integrity": "sha512-Qff39yEOPYgRsm4SrkHOvS0nSoxXILYnC8Akp0uMRi2lOcZVyXL3WCWqIOtI830qVI4GPa796sleKguxx50RHg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.953.0", - "@smithy/types": "^4.10.0", + "@aws-sdk/types": "3.956.0", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.953.0.tgz", - "integrity": "sha512-cmIJx0gWeesUKK4YwgE+VQL3mpACr3/J24fbwnc1Z5tntC86b+HQFzU5vsBDw6lLwyD46dBgWdsXFh1jL+ZaFw==", + "node_modules/@aws-sdk/client-sns/node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.956.0.tgz", + "integrity": "sha512-/f4JxL2kSCYhy63wovqts6SJkpalSLvuFe78ozt3ClrGoHGyr69o7tPRYx5U7azLgvrIGjsWUyTayeAk3YHIVQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.953.0", + "@aws-sdk/types": "3.956.0", "@aws/lambda-invoke-store": "^0.2.2", - "@smithy/protocol-http": "^5.3.6", - "@smithy/types": "^4.10.0", + "@smithy/protocol-http": "^5.3.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.953.0.tgz", - "integrity": "sha512-xZSU54cEHlIvRTUewyTAajb4WJPdbBd1mIaDYOzac07+vsfMuCREQ5CheQ3inoBfqske7QOX+mIjLpVV4azAnw==", + "node_modules/@aws-sdk/client-sns/node_modules/@aws-sdk/region-config-resolver": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.956.0.tgz", + "integrity": "sha512-byU5XYekW7+rZ3e067y038wlrpnPkdI4fMxcHCHrv+TAfzl8CCk5xLyzerQtXZR8cVPVOXuaYWe1zKW0uCnXUA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.953.0", - "@aws-sdk/types": "3.953.0", - "@aws-sdk/util-endpoints": "3.953.0", - "@smithy/core": "^3.19.0", - "@smithy/protocol-http": "^5.3.6", - "@smithy/types": "^4.10.0", + "@aws-sdk/types": "3.956.0", + "@smithy/config-resolver": "^4.4.5", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/nested-clients": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.953.0.tgz", - "integrity": "sha512-YEBI0b/4ezNkw5W4+RBRUoueFzqEPPrnkh/3LBqeJ7RWZTymBhxlpoLo6Gfxw9LxtDgv2vZ5K5rgC4/6Ly8ADg==", + "node_modules/@aws-sdk/client-sns/node_modules/@aws-sdk/types": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", + "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-sns/node_modules/@aws-sdk/util-endpoints": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.956.0.tgz", + "integrity": "sha512-xZ5CBoubS4rs9JkFniKNShDtfqxaMUnwaebYMoybZm070q9+omFkQkJYXl7kopTViEgZgQl1sAsAkrawBM8qEQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.956.0", + "@smithy/types": "^4.11.0", + "@smithy/url-parser": "^4.2.7", + "@smithy/util-endpoints": "^3.2.7", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/client-sns/node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.956.0.tgz", + "integrity": "sha512-s8KwYR3HqiGNni7a1DN2P3RUog64QoBQ6VCSzJkHBWb6++8KSOpqeeDkfmEz+22y1LOne+bRrpDGKa0aqOc3rQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.956.0", + "@smithy/types": "^4.11.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/client-sso": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.956.0.tgz", + "integrity": "sha512-TCxCa9B1IMILvk/7sig0fRQzff+M2zBQVZGWOJL8SAZq/gfElIMAf/nYjQwMhXjyq8PFDRGm4GN8ZhNKPeNleQ==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.953.0", - "@aws-sdk/middleware-host-header": "3.953.0", - "@aws-sdk/middleware-logger": "3.953.0", - "@aws-sdk/middleware-recursion-detection": "3.953.0", - "@aws-sdk/middleware-user-agent": "3.953.0", - "@aws-sdk/region-config-resolver": "3.953.0", - "@aws-sdk/types": "3.953.0", - "@aws-sdk/util-endpoints": "3.953.0", - "@aws-sdk/util-user-agent-browser": "3.953.0", - "@aws-sdk/util-user-agent-node": "3.953.0", - "@smithy/config-resolver": "^4.4.4", - "@smithy/core": "^3.19.0", - "@smithy/fetch-http-handler": "^5.3.7", - "@smithy/hash-node": "^4.2.6", - "@smithy/invalid-dependency": "^4.2.6", - "@smithy/middleware-content-length": "^4.2.6", - "@smithy/middleware-endpoint": "^4.3.15", - "@smithy/middleware-retry": "^4.4.15", - "@smithy/middleware-serde": "^4.2.7", - "@smithy/middleware-stack": "^4.2.6", - "@smithy/node-config-provider": "^4.3.6", - "@smithy/node-http-handler": "^4.4.6", - "@smithy/protocol-http": "^5.3.6", - "@smithy/smithy-client": "^4.10.0", - "@smithy/types": "^4.10.0", - "@smithy/url-parser": "^4.2.6", + "@aws-sdk/core": "3.956.0", + "@aws-sdk/middleware-host-header": "3.956.0", + "@aws-sdk/middleware-logger": "3.956.0", + "@aws-sdk/middleware-recursion-detection": "3.956.0", + "@aws-sdk/middleware-user-agent": "3.956.0", + "@aws-sdk/region-config-resolver": "3.956.0", + "@aws-sdk/types": "3.956.0", + "@aws-sdk/util-endpoints": "3.956.0", + "@aws-sdk/util-user-agent-browser": "3.956.0", + "@aws-sdk/util-user-agent-node": "3.956.0", + "@smithy/config-resolver": "^4.4.5", + "@smithy/core": "^3.20.0", + "@smithy/fetch-http-handler": "^5.3.8", + "@smithy/hash-node": "^4.2.7", + "@smithy/invalid-dependency": "^4.2.7", + "@smithy/middleware-content-length": "^4.2.7", + "@smithy/middleware-endpoint": "^4.4.1", + "@smithy/middleware-retry": "^4.4.17", + "@smithy/middleware-serde": "^4.2.8", + "@smithy/middleware-stack": "^4.2.7", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/node-http-handler": "^4.4.7", + "@smithy/protocol-http": "^5.3.7", + "@smithy/smithy-client": "^4.10.2", + "@smithy/types": "^4.11.0", + "@smithy/url-parser": "^4.2.7", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.14", - "@smithy/util-defaults-mode-node": "^4.2.17", - "@smithy/util-endpoints": "^3.2.6", - "@smithy/util-middleware": "^4.2.6", - "@smithy/util-retry": "^4.2.6", + "@smithy/util-defaults-mode-browser": "^4.3.16", + "@smithy/util-defaults-mode-node": "^4.2.19", + "@smithy/util-endpoints": "^3.2.7", + "@smithy/util-middleware": "^4.2.7", + "@smithy/util-retry": "^4.2.7", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" }, @@ -746,139 +705,152 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.953.0.tgz", - "integrity": "sha512-5MJgnsc+HLO+le0EK1cy92yrC7kyhGZSpaq8PcQvKs9qtXCXT5Tb6tMdkr5Y07JxYsYOV1omWBynvL6PWh08tQ==", + "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/middleware-host-header": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.956.0.tgz", + "integrity": "sha512-JujNJDp/dj1DbsI0ntzhrz2uJ4jpumcKtr743eMpEhdboYjuu/UzY8/7n1h5JbgU9TNXgqE9lgQNa5QPG0Tvsg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.953.0", - "@smithy/config-resolver": "^4.4.4", - "@smithy/node-config-provider": "^4.3.6", - "@smithy/types": "^4.10.0", + "@aws-sdk/types": "3.956.0", + "@smithy/protocol-http": "^5.3.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/token-providers": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.953.0.tgz", - "integrity": "sha512-4FWWR3lDDuIftmCEWpGejfkJu2J1VG2MUktChQshADXABfVfM0fsT7OYlO7Sy106nOe9upE4uQTWXg9YT/6ssw==", + "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/middleware-logger": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.956.0.tgz", + "integrity": "sha512-Qff39yEOPYgRsm4SrkHOvS0nSoxXILYnC8Akp0uMRi2lOcZVyXL3WCWqIOtI830qVI4GPa796sleKguxx50RHg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.953.0", - "@aws-sdk/nested-clients": "3.953.0", - "@aws-sdk/types": "3.953.0", - "@smithy/property-provider": "^4.2.6", - "@smithy/shared-ini-file-loader": "^4.4.1", - "@smithy/types": "^4.10.0", + "@aws-sdk/types": "3.956.0", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/types": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.953.0.tgz", - "integrity": "sha512-M9Iwg9kTyqTErI0vOTVVpcnTHWzS3VplQppy8MuL02EE+mJ0BIwpWfsaAPQW+/XnVpdNpWZTsHcNE29f1+hR8g==", + "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.956.0.tgz", + "integrity": "sha512-/f4JxL2kSCYhy63wovqts6SJkpalSLvuFe78ozt3ClrGoHGyr69o7tPRYx5U7azLgvrIGjsWUyTayeAk3YHIVQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.10.0", + "@aws-sdk/types": "3.956.0", + "@aws/lambda-invoke-store": "^0.2.2", + "@smithy/protocol-http": "^5.3.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/util-dynamodb": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.953.0.tgz", - "integrity": "sha512-WxDCCmpyJwAuBly+M7XYxdR9vLH69DjJT/8mWBeaxCcaZQO6W7l8PGGNMSHZQSMcWO5vhqOf0l29ZHdK3a63FA==", + "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/region-config-resolver": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.956.0.tgz", + "integrity": "sha512-byU5XYekW7+rZ3e067y038wlrpnPkdI4fMxcHCHrv+TAfzl8CCk5xLyzerQtXZR8cVPVOXuaYWe1zKW0uCnXUA==", "license": "Apache-2.0", "dependencies": { + "@aws-sdk/types": "3.956.0", + "@smithy/config-resolver": "^4.4.5", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-dynamodb": "^3.953.0" } }, - "node_modules/@aws-sdk/util-endpoints": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.953.0.tgz", - "integrity": "sha512-rjaS6jrFksopXvNg6YeN+D1lYwhcByORNlFuYesFvaQNtPOufbE5tJL4GJ3TMXyaY0uFR28N5BHHITPyWWfH/g==", + "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/types": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", + "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.953.0", - "@smithy/types": "^4.10.0", - "@smithy/url-parser": "^4.2.6", - "@smithy/util-endpoints": "^3.2.6", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/util-locate-window": { - "version": "3.893.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.893.0.tgz", - "integrity": "sha512-T89pFfgat6c8nMmpI8eKjBcDcgJq36+m9oiXbcUzeU55MP9ZuGgBomGjGnHaEyF36jenW9gmg3NfZDm0AO2XPg==", + "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/util-endpoints": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.956.0.tgz", + "integrity": "sha512-xZ5CBoubS4rs9JkFniKNShDtfqxaMUnwaebYMoybZm070q9+omFkQkJYXl7kopTViEgZgQl1sAsAkrawBM8qEQ==", "license": "Apache-2.0", "dependencies": { + "@aws-sdk/types": "3.956.0", + "@smithy/types": "^4.11.0", + "@smithy/url-parser": "^4.2.7", + "@smithy/util-endpoints": "^3.2.7", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.953.0.tgz", - "integrity": "sha512-UF5NeqYesWuFao+u7LJvpV1SJCaLml5BtFZKUdTnNNMeN6jvV+dW/eQoFGpXF94RCqguX0XESmRuRRPQp+/rzQ==", + "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.956.0.tgz", + "integrity": "sha512-s8KwYR3HqiGNni7a1DN2P3RUog64QoBQ6VCSzJkHBWb6++8KSOpqeeDkfmEz+22y1LOne+bRrpDGKa0aqOc3rQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.953.0", - "@smithy/types": "^4.10.0", + "@aws-sdk/types": "3.956.0", + "@smithy/types": "^4.11.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, - "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.953.0.tgz", - "integrity": "sha512-HjJ0Nq/57kg0QCjt8mwBAK6C34njKezy9ItUNcrWITzrBZv7ikQtyqM1pindAIzgLaBb7ly/0kbJqMY+NPbcJA==", + "node_modules/@aws-sdk/core": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.956.0.tgz", + "integrity": "sha512-BMOCXZNz5z4cR3/SaNHUfeoZQUG/y39bLscdLUgg3RL6mDOhuINIqMc0qc6G3kpwDTLVdXikF4nmx2UrRK9y5A==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-user-agent": "3.953.0", - "@aws-sdk/types": "3.953.0", - "@smithy/node-config-provider": "^4.3.6", - "@smithy/types": "^4.10.0", + "@aws-sdk/types": "3.956.0", + "@aws-sdk/xml-builder": "3.956.0", + "@smithy/core": "^3.20.0", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/property-provider": "^4.2.7", + "@smithy/protocol-http": "^5.3.7", + "@smithy/signature-v4": "^5.3.7", + "@smithy/smithy-client": "^4.10.2", + "@smithy/types": "^4.11.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-middleware": "^4.2.7", + "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" + } + }, + "node_modules/@aws-sdk/core/node_modules/@aws-sdk/types": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", + "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "aws-crt": ">=1.0.0" - }, - "peerDependenciesMeta": { - "aws-crt": { - "optional": true - } + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/xml-builder": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.953.0.tgz", - "integrity": "sha512-Zmrj21jQ2OeOJGr9spPiN00aQvXa/WUqRXcTVENhrMt+OFoSOfDFpYhUj9NQ09QmQ8KMWFoWuWW6iKurNqLvAA==", + "node_modules/@aws-sdk/core/node_modules/@aws-sdk/xml-builder": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.956.0.tgz", + "integrity": "sha512-x/IvXUeQYNUEQojpRIQpFt4X7XGxqzjUlXFRdwaTCtTz3q1droXVJvYOhnX3KiMgzeHGlBJfY4Nmq3oZNEUGFw==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.10.0", + "@smithy/types": "^4.11.0", "fast-xml-parser": "5.2.5", "tslib": "^2.6.2" }, @@ -886,1402 +858,2595 @@ "node": ">=18.0.0" } }, - "node_modules/@aws/lambda-invoke-store": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.2.tgz", - "integrity": "sha512-C0NBLsIqzDIae8HFw9YIrIBsbc0xTiOtt7fAukGPnqQ/+zZNaq+4jhuccltK0QuWHBnNm/a6kLIRA6GFiM10eg==", + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.956.0.tgz", + "integrity": "sha512-aLJavJMPVTvhmggJ0pcdCKEWJk3sL9QkJkUIEoTzOou7HnxWS66N4sC5e8y27AF2nlnYfIxq3hkEiZlGi/vlfA==", "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.956.0", + "@aws-sdk/types": "3.956.0", + "@smithy/property-provider": "^4.2.7", + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" + }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-env/node_modules/@aws-sdk/types": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", + "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/@babel/compat-data": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", - "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.956.0.tgz", + "integrity": "sha512-VsKzBNhwT6XJdW3HQX6o4KOHj1MAzSwA8/zCsT9mOGecozw1yeCcQPtlWDSlfsfygKVCXz7fiJzU03yl11NKMA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.956.0", + "@aws-sdk/types": "3.956.0", + "@smithy/fetch-http-handler": "^5.3.8", + "@smithy/node-http-handler": "^4.4.7", + "@smithy/property-provider": "^4.2.7", + "@smithy/protocol-http": "^5.3.7", + "@smithy/smithy-client": "^4.10.2", + "@smithy/types": "^4.11.0", + "@smithy/util-stream": "^4.5.8", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/@babel/core": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", - "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", - "dev": true, - "license": "MIT", - "peer": true, + "node_modules/@aws-sdk/credential-provider-http/node_modules/@aws-sdk/types": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", + "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", + "license": "Apache-2.0", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.5", - "@babel/types": "^7.28.5", - "@jridgewell/remapping": "^2.3.5", - "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/types": "^4.11.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" + "node": ">=18.0.0" } }, - "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==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.956.0.tgz", + "integrity": "sha512-TlDy+IGr0JIRBwnPdV31J1kWXEcfsR3OzcNVWQrguQdHeTw2lU5eft16kdizo6OruqcZRF/LvHBDwAWx4u51ww==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.956.0", + "@aws-sdk/credential-provider-env": "3.956.0", + "@aws-sdk/credential-provider-http": "3.956.0", + "@aws-sdk/credential-provider-login": "3.956.0", + "@aws-sdk/credential-provider-process": "3.956.0", + "@aws-sdk/credential-provider-sso": "3.956.0", + "@aws-sdk/credential-provider-web-identity": "3.956.0", + "@aws-sdk/nested-clients": "3.956.0", + "@aws-sdk/types": "3.956.0", + "@smithy/credential-provider-imds": "^4.2.7", + "@smithy/property-provider": "^4.2.7", + "@smithy/shared-ini-file-loader": "^4.4.2", + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@babel/generator": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", - "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-ini/node_modules/@aws-sdk/types": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", + "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", + "license": "Apache-2.0", "dependencies": { - "@babel/parser": "^7.28.5", - "@babel/types": "^7.28.5", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-login": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.956.0.tgz", + "integrity": "sha512-p2Y62mdIlUpiyi5tvn8cKTja5kq1e3Rm5gm4wpNQ9caTayfkIEXyKrbP07iepTv60Coaylq9Fx6b5En/siAeGA==", + "license": "Apache-2.0", "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" + "@aws-sdk/core": "3.956.0", + "@aws-sdk/nested-clients": "3.956.0", + "@aws-sdk/types": "3.956.0", + "@smithy/property-provider": "^4.2.7", + "@smithy/protocol-http": "^5.3.7", + "@smithy/shared-ini-file-loader": "^4.4.2", + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "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==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/types": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", + "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.956.0.tgz", + "integrity": "sha512-ITjp7uAQh17ljUsCWkPRmLjyFfupGlJVUfTLHnZJ+c7G0P0PDRquaM+fBSh0y33tauHsBa5fGnCCLRo5hy9sGQ==", + "license": "Apache-2.0", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@aws-sdk/credential-provider-env": "3.956.0", + "@aws-sdk/credential-provider-http": "3.956.0", + "@aws-sdk/credential-provider-ini": "3.956.0", + "@aws-sdk/credential-provider-process": "3.956.0", + "@aws-sdk/credential-provider-sso": "3.956.0", + "@aws-sdk/credential-provider-web-identity": "3.956.0", + "@aws-sdk/types": "3.956.0", + "@smithy/credential-provider-imds": "^4.2.7", + "@smithy/property-provider": "^4.2.7", + "@smithy/shared-ini-file-loader": "^4.4.2", + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", - "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-node/node_modules/@aws-sdk/types": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", + "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.28.3" - }, - "engines": { - "node": ">=6.9.0" + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", - "dev": true, - "license": "MIT", "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.956.0.tgz", + "integrity": "sha512-wpAex+/LGVWkHPchsn9FWy1ahFualIeSYq3ADFc262ljJjrltOWGh3+cu3OK3gTMkX6VEsl+lFvy1P7Bk7cgXA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.956.0", + "@aws-sdk/types": "3.956.0", + "@smithy/property-provider": "^4.2.7", + "@smithy/shared-ini-file-loader": "^4.4.2", + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-process/node_modules/@aws-sdk/types": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", + "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.956.0.tgz", + "integrity": "sha512-IRFSDF32x8TpOEYSGMcGQVJUiYuJaFkek0aCjW0klNIZHBF1YpflVpUarK9DJe4v4ryfVq3c0bqR/JFui8QFmw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/client-sso": "3.956.0", + "@aws-sdk/core": "3.956.0", + "@aws-sdk/token-providers": "3.956.0", + "@aws-sdk/types": "3.956.0", + "@smithy/property-provider": "^4.2.7", + "@smithy/shared-ini-file-loader": "^4.4.2", + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/@babel/helpers": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", - "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/types": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", + "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", + "license": "Apache-2.0", "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4" + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/@babel/parser": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", - "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.956.0.tgz", + "integrity": "sha512-4YkmjwZC+qoUKlVOY9xNx7BTKRdJ1R1/Zjk2QSW5aWtwkk2e07ZUQvUpbW4vGpAxGm1K4EgRcowuSpOsDTh44Q==", + "license": "Apache-2.0", "dependencies": { - "@babel/types": "^7.28.5" - }, - "bin": { - "parser": "bin/babel-parser.js" + "@aws-sdk/core": "3.956.0", + "@aws-sdk/nested-clients": "3.956.0", + "@aws-sdk/types": "3.956.0", + "@smithy/property-provider": "^4.2.7", + "@smithy/shared-ini-file-loader": "^4.4.2", + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.0.0" + "node": ">=18.0.0" } }, - "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==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/credential-provider-web-identity/node_modules/@aws-sdk/types": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", + "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "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==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/dynamodb-codec": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/dynamodb-codec/-/dynamodb-codec-3.956.0.tgz", + "integrity": "sha512-18+va/liQYkUVn5Wdz7h4rQQHq5QplFmQBAnkIOpZoN4ir36lrS9IeyoRbcrj8AxZRTHzl+vGc69Bq3sq9s5xg==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@aws-sdk/core": "3.956.0", + "@smithy/core": "^3.20.0", + "@smithy/smithy-client": "^4.10.2", + "@smithy/types": "^4.11.0", + "@smithy/util-base64": "^4.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@aws-sdk/client-dynamodb": "^3.956.0" } }, - "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==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/endpoint-cache": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.953.0.tgz", + "integrity": "sha512-pz67DoHk5WNmvMuyNDiomUS2xo0mq6Z3TdfLJZlWVbSKi3h8hYxVQchJ2kzgTr6wu6zt3UBbtKV9yY1IBhKMVA==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" + "mnemonist": "0.38.3", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "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==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/lib-dynamodb": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.956.0.tgz", + "integrity": "sha512-RA21BJsFS3tqellTGURz0oqf/xGZcK2xUow9sXl17SaC8ukYvIsUyPf8q+RcCVsXVezKG9n6yJhEsHemnNjH5Q==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@aws-sdk/core": "3.956.0", + "@aws-sdk/util-dynamodb": "3.956.0", + "@smithy/core": "^3.20.0", + "@smithy/smithy-client": "^4.10.2", + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@aws-sdk/client-dynamodb": "^3.956.0" } }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", - "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/middleware-endpoint-discovery": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.953.0.tgz", + "integrity": "sha512-/YKB1/OiWr7TwOfmkqzv8x1xgOpU71yciQTfsq6erB3dTQhdukPADt/CMJOhWFKC6Q1D5cDN8381nsGmnNuBVg==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@aws-sdk/endpoint-cache": "3.953.0", + "@aws-sdk/types": "3.953.0", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/protocol-http": "^5.3.6", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18.0.0" } }, - "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==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.953.0.tgz", + "integrity": "sha512-jTGhfkONav+r4E6HLOrl5SzBqDmPByUYCkyB/c/3TVb8jX3wAZx8/q9bphKpCh+G5ARi3IdbSisgkZrJYqQ19Q==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@aws-sdk/types": "3.953.0", + "@smithy/protocol-http": "^5.3.6", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "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==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.953.0.tgz", + "integrity": "sha512-PlWdVYgcuptkIC0ZKqVUhWNtSHXJSx7U9V8J7dJjRmsXC40X7zpEycvrkzDMJjeTDGcCceYbyYAg/4X1lkcIMw==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@aws-sdk/types": "3.953.0", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", - "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.953.0.tgz", + "integrity": "sha512-cmIJx0gWeesUKK4YwgE+VQL3mpACr3/J24fbwnc1Z5tntC86b+HQFzU5vsBDw6lLwyD46dBgWdsXFh1jL+ZaFw==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@aws-sdk/types": "3.953.0", + "@aws/lambda-invoke-store": "^0.2.2", + "@smithy/protocol-http": "^5.3.6", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18.0.0" } }, - "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==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.956.0.tgz", + "integrity": "sha512-azH8OJ0AIe3NafaTNvJorG/ALaLNTYwVKtyaSeQKOvaL8TNuBVuDnM5iHCiWryIaRgZotomqycwyfNKLw2D3JQ==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@aws-sdk/core": "3.956.0", + "@aws-sdk/types": "3.956.0", + "@aws-sdk/util-endpoints": "3.956.0", + "@smithy/core": "^3.20.0", + "@smithy/protocol-http": "^5.3.7", + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "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==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/middleware-user-agent/node_modules/@aws-sdk/types": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", + "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "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==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/middleware-user-agent/node_modules/@aws-sdk/util-endpoints": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.956.0.tgz", + "integrity": "sha512-xZ5CBoubS4rs9JkFniKNShDtfqxaMUnwaebYMoybZm070q9+omFkQkJYXl7kopTViEgZgQl1sAsAkrawBM8qEQ==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@aws-sdk/types": "3.956.0", + "@smithy/types": "^4.11.0", + "@smithy/url-parser": "^4.2.7", + "@smithy/util-endpoints": "^3.2.7", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "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==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/nested-clients": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.956.0.tgz", + "integrity": "sha512-GHDQMkxoWpi3eTrhWGmghw0gsZJ5rM1ERHfBFhlhduCdtV3TyhKVmDgFG84KhU8v18dcVpSp3Pu3KwH7j1tgIg==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.956.0", + "@aws-sdk/middleware-host-header": "3.956.0", + "@aws-sdk/middleware-logger": "3.956.0", + "@aws-sdk/middleware-recursion-detection": "3.956.0", + "@aws-sdk/middleware-user-agent": "3.956.0", + "@aws-sdk/region-config-resolver": "3.956.0", + "@aws-sdk/types": "3.956.0", + "@aws-sdk/util-endpoints": "3.956.0", + "@aws-sdk/util-user-agent-browser": "3.956.0", + "@aws-sdk/util-user-agent-node": "3.956.0", + "@smithy/config-resolver": "^4.4.5", + "@smithy/core": "^3.20.0", + "@smithy/fetch-http-handler": "^5.3.8", + "@smithy/hash-node": "^4.2.7", + "@smithy/invalid-dependency": "^4.2.7", + "@smithy/middleware-content-length": "^4.2.7", + "@smithy/middleware-endpoint": "^4.4.1", + "@smithy/middleware-retry": "^4.4.17", + "@smithy/middleware-serde": "^4.2.8", + "@smithy/middleware-stack": "^4.2.7", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/node-http-handler": "^4.4.7", + "@smithy/protocol-http": "^5.3.7", + "@smithy/smithy-client": "^4.10.2", + "@smithy/types": "^4.11.0", + "@smithy/url-parser": "^4.2.7", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.16", + "@smithy/util-defaults-mode-node": "^4.2.19", + "@smithy/util-endpoints": "^3.2.7", + "@smithy/util-middleware": "^4.2.7", + "@smithy/util-retry": "^4.2.7", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "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==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/middleware-host-header": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.956.0.tgz", + "integrity": "sha512-JujNJDp/dj1DbsI0ntzhrz2uJ4jpumcKtr743eMpEhdboYjuu/UzY8/7n1h5JbgU9TNXgqE9lgQNa5QPG0Tvsg==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@aws-sdk/types": "3.956.0", + "@smithy/protocol-http": "^5.3.7", + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "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==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/middleware-logger": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.956.0.tgz", + "integrity": "sha512-Qff39yEOPYgRsm4SrkHOvS0nSoxXILYnC8Akp0uMRi2lOcZVyXL3WCWqIOtI830qVI4GPa796sleKguxx50RHg==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@aws-sdk/types": "3.956.0", + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=18.0.0" } }, - "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==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.956.0.tgz", + "integrity": "sha512-/f4JxL2kSCYhy63wovqts6SJkpalSLvuFe78ozt3ClrGoHGyr69o7tPRYx5U7azLgvrIGjsWUyTayeAk3YHIVQ==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@aws-sdk/types": "3.956.0", + "@aws/lambda-invoke-store": "^0.2.2", + "@smithy/protocol-http": "^5.3.7", + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18.0.0" } }, - "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==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/region-config-resolver": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.956.0.tgz", + "integrity": "sha512-byU5XYekW7+rZ3e067y038wlrpnPkdI4fMxcHCHrv+TAfzl8CCk5xLyzerQtXZR8cVPVOXuaYWe1zKW0uCnXUA==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@aws-sdk/types": "3.956.0", + "@smithy/config-resolver": "^4.4.5", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18.0.0" } }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", - "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/types": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", + "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=18.0.0" } }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/util-endpoints": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.956.0.tgz", + "integrity": "sha512-xZ5CBoubS4rs9JkFniKNShDtfqxaMUnwaebYMoybZm070q9+omFkQkJYXl7kopTViEgZgQl1sAsAkrawBM8qEQ==", + "license": "Apache-2.0", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" + "@aws-sdk/types": "3.956.0", + "@smithy/types": "^4.11.0", + "@smithy/url-parser": "^4.2.7", + "@smithy/util-endpoints": "^3.2.7", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "node_modules/@babel/traverse": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", - "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.956.0.tgz", + "integrity": "sha512-s8KwYR3HqiGNni7a1DN2P3RUog64QoBQ6VCSzJkHBWb6++8KSOpqeeDkfmEz+22y1LOne+bRrpDGKa0aqOc3rQ==", + "license": "Apache-2.0", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.5", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" + "@aws-sdk/types": "3.956.0", + "@smithy/types": "^4.11.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" } }, - "node_modules/@babel/types": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", - "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.953.0.tgz", + "integrity": "sha512-5MJgnsc+HLO+le0EK1cy92yrC7kyhGZSpaq8PcQvKs9qtXCXT5Tb6tMdkr5Y07JxYsYOV1omWBynvL6PWh08tQ==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" + "@aws-sdk/types": "3.953.0", + "@smithy/config-resolver": "^4.4.4", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=18.0.0" } }, - "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==", - "dev": true, - "license": "MIT" - }, - "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==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/token-providers": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.956.0.tgz", + "integrity": "sha512-I01Q9yDeG9oXge14u/bubtSdBpok/rTsPp2AQwy5xj/5PatRTHPbUTP6tef3AH/lFCAqkI0nncIcgx6zikDdUQ==", + "license": "Apache-2.0", "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" + "@aws-sdk/core": "3.956.0", + "@aws-sdk/nested-clients": "3.956.0", + "@aws-sdk/types": "3.956.0", + "@smithy/property-provider": "^4.2.7", + "@smithy/shared-ini-file-loader": "^4.4.2", + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=12" + "node": ">=18.0.0" } }, - "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==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/token-providers/node_modules/@aws-sdk/types": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", + "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", + "license": "Apache-2.0", "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@emnapi/core": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz", - "integrity": "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==", - "dev": true, - "license": "MIT", - "optional": true, + "node_modules/@aws-sdk/types": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.953.0.tgz", + "integrity": "sha512-M9Iwg9kTyqTErI0vOTVVpcnTHWzS3VplQppy8MuL02EE+mJ0BIwpWfsaAPQW+/XnVpdNpWZTsHcNE29f1+hR8g==", + "license": "Apache-2.0", "dependencies": { - "@emnapi/wasi-threads": "1.1.0", - "tslib": "^2.4.0" + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@emnapi/runtime": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", - "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", - "dev": true, - "license": "MIT", - "optional": true, + "node_modules/@aws-sdk/util-dynamodb": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.956.0.tgz", + "integrity": "sha512-RZrYUZ9zacb7t2+CeD+/UkVriIQ3N4MyQi+f/KPEbqZ1mYg1yXo/kFvUL4Qdi28qve/pG3J3R1tx9eb6nMW1uQ==", + "license": "Apache-2.0", "dependencies": { - "tslib": "^2.4.0" + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-dynamodb": "^3.956.0" } }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", - "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", - "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.953.0.tgz", + "integrity": "sha512-rjaS6jrFksopXvNg6YeN+D1lYwhcByORNlFuYesFvaQNtPOufbE5tJL4GJ3TMXyaY0uFR28N5BHHITPyWWfH/g==", + "license": "Apache-2.0", "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "@aws-sdk/types": "3.953.0", + "@smithy/types": "^4.10.0", + "@smithy/url-parser": "^4.2.6", + "@smithy/util-endpoints": "^3.2.6", + "tslib": "^2.6.2" }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", - "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", - "dev": true, - "license": "MIT", "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=18.0.0" } }, - "node_modules/@eslint/config-array": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", - "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", - "dev": true, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.893.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.893.0.tgz", + "integrity": "sha512-T89pFfgat6c8nMmpI8eKjBcDcgJq36+m9oiXbcUzeU55MP9ZuGgBomGjGnHaEyF36jenW9gmg3NfZDm0AO2XPg==", "license": "Apache-2.0", "dependencies": { - "@eslint/object-schema": "^2.1.7", - "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/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.953.0.tgz", + "integrity": "sha512-UF5NeqYesWuFao+u7LJvpV1SJCaLml5BtFZKUdTnNNMeN6jvV+dW/eQoFGpXF94RCqguX0XESmRuRRPQp+/rzQ==", + "license": "Apache-2.0", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@aws-sdk/types": "3.953.0", + "@smithy/types": "^4.10.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" } }, - "node_modules/@eslint/config-array/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", + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.956.0.tgz", + "integrity": "sha512-H0r6ol3Rr63/3xvrUsLqHps+cA7VkM7uCU5NtuTHnMbv3uYYTKf9M2XFHAdVewmmRgssTzvqemrARc8Ji3SNvg==", + "license": "Apache-2.0", "dependencies": { - "brace-expansion": "^1.1.7" + "@aws-sdk/middleware-user-agent": "3.956.0", + "@aws-sdk/types": "3.956.0", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" }, "engines": { - "node": "*" + "node": ">=18.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } } }, - "node_modules/@eslint/config-helpers": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", - "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", - "dev": true, + "node_modules/@aws-sdk/util-user-agent-node/node_modules/@aws-sdk/types": { + "version": "3.956.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", + "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.17.0" + "@smithy/types": "^4.11.0", + "tslib": "^2.6.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18.0.0" } }, - "node_modules/@eslint/core": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", - "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", - "dev": true, + "node_modules/@aws-sdk/xml-builder": { + "version": "3.953.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.953.0.tgz", + "integrity": "sha512-Zmrj21jQ2OeOJGr9spPiN00aQvXa/WUqRXcTVENhrMt+OFoSOfDFpYhUj9NQ09QmQ8KMWFoWuWW6iKurNqLvAA==", "license": "Apache-2.0", "dependencies": { - "@types/json-schema": "^7.0.15" + "@smithy/types": "^4.10.0", + "fast-xml-parser": "5.2.5", + "tslib": "^2.6.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=18.0.0" } }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", - "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "node_modules/@aws/lambda-invoke-store": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.2.tgz", + "integrity": "sha512-C0NBLsIqzDIae8HFw9YIrIBsbc0xTiOtt7fAukGPnqQ/+zZNaq+4jhuccltK0QuWHBnNm/a6kLIRA6GFiM10eg==", + "license": "Apache-2.0", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, "license": "MIT", "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.1", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=6.9.0" } }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/@babel/compat-data": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "node_modules/@babel/core": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", + "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@eslint/eslintrc/node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "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==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@babel/generator": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" }, "engines": { - "node": "*" + "node": ">=6.9.0" } }, - "node_modules/@eslint/js": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", - "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "dev": true, "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, - "funding": { - "url": "https://eslint.org/donate" - } - }, - "node_modules/@eslint/object-schema": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", - "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", - "dev": true, - "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=6.9.0" } }, - "node_modules/@eslint/plugin-kit": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", - "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "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==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.17.0", - "levn": "^0.4.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "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==", + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": ">=18.18.0" + "node": ">=6.9.0" } }, - "node_modules/@humanfs/node": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", - "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.4.0" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { - "node": ">=18.18.0" + "node": ">=6.9.0" } }, - "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==", + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, "engines": { - "node": ">=12.22" + "node": ">=6.9.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@humanwhocodes/retry": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", - "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "node": ">=6.9.0" } }, - "node_modules/@isaacs/balanced-match": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", - "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, "license": "MIT", "engines": { - "node": "20 || >=22" + "node": ">=6.9.0" } }, - "node_modules/@isaacs/brace-expansion": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", - "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true, "license": "MIT", - "dependencies": { - "@isaacs/balanced-match": "^4.0.1" - }, "engines": { - "node": "20 || >=22" + "node": ">=6.9.0" } }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=6.9.0" } }, - "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==", + "node_modules/@babel/helpers": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", "dev": true, - "license": "ISC", + "license": "MIT", "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" + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@babel/parser": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", "dev": true, "license": "MIT", "dependencies": { - "sprintf-js": "~1.0.2" + "@babel/types": "^7.28.5" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config/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==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "@babel/helper-plugin-utils": "^7.8.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@istanbuljs/load-nyc-config/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==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "@babel/helper-plugin-utils": "^7.12.13" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@istanbuljs/load-nyc-config/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==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { - "node": ">=6" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@istanbuljs/load-nyc-config/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==", + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", "dev": true, "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@istanbuljs/load-nyc-config/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==", + "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==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.2.0.tgz", - "integrity": "sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", - "@types/node": "*", - "chalk": "^4.1.2", - "jest-message-util": "30.2.0", - "jest-util": "30.2.0", - "slash": "^3.0.0" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/core": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.2.0.tgz", - "integrity": "sha512-03W6IhuhjqTlpzh/ojut/pDB2LPRygyWX8ExpgHtQA8H/3K7+1vKmcINx5UzeOX1se6YEsBsOHQ1CRzf3fOwTQ==", + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "30.2.0", - "@jest/pattern": "30.0.1", - "@jest/reporters": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", - "@types/node": "*", - "ansi-escapes": "^4.3.2", - "chalk": "^4.1.2", - "ci-info": "^4.2.0", - "exit-x": "^0.2.2", - "graceful-fs": "^4.2.11", - "jest-changed-files": "30.2.0", - "jest-config": "30.2.0", - "jest-haste-map": "30.2.0", - "jest-message-util": "30.2.0", - "jest-regex-util": "30.0.1", - "jest-resolve": "30.2.0", - "jest-resolve-dependencies": "30.2.0", - "jest-runner": "30.2.0", - "jest-runtime": "30.2.0", - "jest-snapshot": "30.2.0", - "jest-util": "30.2.0", - "jest-validate": "30.2.0", - "jest-watcher": "30.2.0", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", - "slash": "^3.0.0" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/diff-sequences": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", - "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", + "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==", "dev": true, "license": "MIT", - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/environment": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.2.0.tgz", - "integrity": "sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "@jest/fake-timers": "30.2.0", - "@jest/types": "30.2.0", - "@types/node": "*", - "jest-mock": "30.2.0" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/expect": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.2.0.tgz", - "integrity": "sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "expect": "30.2.0", - "jest-snapshot": "30.2.0" + "@babel/helper-plugin-utils": "^7.10.4" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/expect-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz", - "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "@jest/get-type": "30.1.0" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/fake-timers": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.2.0.tgz", - "integrity": "sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", - "@sinonjs/fake-timers": "^13.0.0", - "@types/node": "*", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", - "jest-util": "30.2.0" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/get-type": { - "version": "30.1.0", - "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz", - "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==", + "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==", "dev": true, "license": "MIT", - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/globals": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.2.0.tgz", - "integrity": "sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.2.0", - "@jest/expect": "30.2.0", - "@jest/types": "30.2.0", - "jest-mock": "30.2.0" + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/pattern": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz", - "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*", - "jest-regex-util": "30.0.1" + "@babel/helper-plugin-utils": "^7.14.5" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/reporters": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.2.0.tgz", - "integrity": "sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ==", + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", "dev": true, "license": "MIT", "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "30.2.0", - "@jest/test-result": "30.2.0", - "@jest/transform": "30.2.0", - "@jest/types": "30.2.0", - "@jridgewell/trace-mapping": "^0.3.25", - "@types/node": "*", - "chalk": "^4.1.2", - "collect-v8-coverage": "^1.0.2", - "exit-x": "^0.2.2", - "glob": "^10.3.10", - "graceful-fs": "^4.2.11", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^5.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "30.2.0", - "jest-util": "30.2.0", - "jest-worker": "30.2.0", - "slash": "^3.0.0", - "string-length": "^4.0.2", - "v8-to-istanbul": "^9.0.1" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=6.9.0" }, "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jest/schemas": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", - "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, "license": "MIT", "dependencies": { - "@sinclair/typebox": "^0.34.0" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=6.9.0" } }, - "node_modules/@jest/snapshot-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.2.0.tgz", - "integrity": "sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==", - "dev": true, + "node_modules/@babel/traverse": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", + "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.2.0", - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "natural-compare": "^1.4.0" + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.5", + "debug": "^4.3.1" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=6.9.0" } }, - "node_modules/@jest/source-map": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz", - "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==", + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", - "callsites": "^3.1.0", - "graceful-fs": "^4.2.11" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=6.9.0" } }, - "node_modules/@jest/test-result": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.2.0.tgz", - "integrity": "sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg==", + "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==", + "dev": true, + "license": "MIT" + }, + "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==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "30.2.0", - "@jest/types": "30.2.0", - "@types/istanbul-lib-coverage": "^2.0.6", - "collect-v8-coverage": "^1.0.2" + "@jridgewell/trace-mapping": "0.3.9" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=12" } }, - "node_modules/@jest/test-sequencer": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.2.0.tgz", - "integrity": "sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "@jest/test-result": "30.2.0", - "graceful-fs": "^4.2.11", - "jest-haste-map": "30.2.0", - "slash": "^3.0.0" + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@emnapi/core": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz", + "integrity": "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", + "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", + "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "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_modules/@jest/transform": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.2.0.tgz", - "integrity": "sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==", + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "@babel/core": "^7.27.4", - "@jest/types": "30.2.0", - "@jridgewell/trace-mapping": "^0.3.25", - "babel-plugin-istanbul": "^7.0.1", - "chalk": "^4.1.2", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.11", - "jest-haste-map": "30.2.0", - "jest-regex-util": "30.0.1", - "jest-util": "30.2.0", - "micromatch": "^4.0.8", - "pirates": "^4.0.7", - "slash": "^3.0.0", - "write-file-atomic": "^5.0.1" + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/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/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "dev": true, + "license": "MIT", + "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.1", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@eslint/eslintrc/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/@eslint/js": { + "version": "9.39.2", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", + "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "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==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", + "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "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==", + "dev": true, + "license": "ISC", + "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" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.2.0.tgz", + "integrity": "sha512-+O1ifRjkvYIkBqASKWgLxrpEhQAAE7hY77ALLUufSk5717KfOShg6IbqLmdsLMPdUiFvA2kTs0R7YZy+l0IzZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@types/node": "*", + "chalk": "^4.1.2", + "jest-message-util": "30.2.0", + "jest-util": "30.2.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/core": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.2.0.tgz", + "integrity": "sha512-03W6IhuhjqTlpzh/ojut/pDB2LPRygyWX8ExpgHtQA8H/3K7+1vKmcINx5UzeOX1se6YEsBsOHQ1CRzf3fOwTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.2.0", + "@jest/pattern": "30.0.1", + "@jest/reporters": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-changed-files": "30.2.0", + "jest-config": "30.2.0", + "jest-haste-map": "30.2.0", + "jest-message-util": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.2.0", + "jest-resolve-dependencies": "30.2.0", + "jest-runner": "30.2.0", + "jest-runtime": "30.2.0", + "jest-snapshot": "30.2.0", + "jest-util": "30.2.0", + "jest-validate": "30.2.0", + "jest-watcher": "30.2.0", + "micromatch": "^4.0.8", + "pretty-format": "30.2.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/diff-sequences": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", + "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/environment": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.2.0.tgz", + "integrity": "sha512-/QPTL7OBJQ5ac09UDRa3EQes4gt1FTEG/8jZ/4v5IVzx+Cv7dLxlVIvfvSVRiiX2drWyXeBjkMSR8hvOWSog5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "30.2.0", + "@jest/types": "30.2.0", + "@types/node": "*", + "jest-mock": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.2.0.tgz", + "integrity": "sha512-V9yxQK5erfzx99Sf+7LbhBwNWEZ9eZay8qQ9+JSC0TrMR1pMDHLMY+BnVPacWU6Jamrh252/IKo4F1Xn/zfiqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "30.2.0", + "jest-snapshot": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz", + "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.2.0.tgz", + "integrity": "sha512-HI3tRLjRxAbBy0VO8dqqm7Hb2mIa8d5bg/NJkyQcOk7V118ObQML8RC5luTF/Zsg4474a+gDvhce7eTnP4GhYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "@sinonjs/fake-timers": "^13.0.0", + "@types/node": "*", + "jest-message-util": "30.2.0", + "jest-mock": "30.2.0", + "jest-util": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/get-type": { + "version": "30.1.0", + "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz", + "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.2.0.tgz", + "integrity": "sha512-b63wmnKPaK+6ZZfpYhz9K61oybvbI1aMcIs80++JI1O1rR1vaxHUCNqo3ITu6NU0d4V34yZFoHMn/uoKr/Rwfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "30.2.0", + "@jest/expect": "30.2.0", + "@jest/types": "30.2.0", + "jest-mock": "30.2.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/pattern": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz", + "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-regex-util": "30.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.2.0.tgz", + "integrity": "sha512-DRyW6baWPqKMa9CzeiBjHwjd8XeAyco2Vt8XbcLFjiwCOEKOvy82GJ8QQnJE9ofsxCMPjH4MfH8fCWIHHDKpAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "30.2.0", + "@jest/test-result": "30.2.0", + "@jest/transform": "30.2.0", + "@jest/types": "30.2.0", + "@jridgewell/trace-mapping": "^0.3.25", + "@types/node": "*", + "chalk": "^4.1.2", + "collect-v8-coverage": "^1.0.2", + "exit-x": "^0.2.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^5.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "30.2.0", + "jest-util": "30.2.0", + "jest-worker": "30.2.0", + "slash": "^3.0.0", + "string-length": "^4.0.2", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/schemas": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", + "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/snapshot-utils": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.2.0.tgz", + "integrity": "sha512-0aVxM3RH6DaiLcjj/b0KrIBZhSX1373Xci4l3cW5xiUWPctZ59zQ7jj4rqcJQ/Z8JuN/4wX3FpJSa3RssVvCug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "30.2.0", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "natural-compare": "^1.4.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz", + "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "callsites": "^3.1.0", + "graceful-fs": "^4.2.11" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.2.0.tgz", + "integrity": "sha512-RF+Z+0CCHkARz5HT9mcQCBulb1wgCP3FBvl9VFokMX27acKphwyQsNuWH3c+ojd1LeWBLoTYoxF0zm6S/66mjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "30.2.0", + "@jest/types": "30.2.0", + "@types/istanbul-lib-coverage": "^2.0.6", + "collect-v8-coverage": "^1.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.2.0.tgz", + "integrity": "sha512-wXKgU/lk8fKXMu/l5Hog1R61bL4q5GCdT6OJvdAFz1P+QrpoFuLU68eoKuVc4RbrTtNnTL5FByhWdLgOPSph+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "30.2.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.2.0.tgz", + "integrity": "sha512-XsauDV82o5qXbhalKxD7p4TZYYdwcaEXC77PPD2HixEFF+6YGppjrAAQurTl2ECWcEomHBMMNS9AH3kcCFx8jA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/types": "30.2.0", + "@jridgewell/trace-mapping": "^0.3.25", + "babel-plugin-istanbul": "^7.0.1", + "chalk": "^4.1.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.2.0", + "jest-regex-util": "30.0.1", + "jest-util": "30.2.0", + "micromatch": "^4.0.8", + "pirates": "^4.0.7", + "slash": "^3.0.0", + "write-file-atomic": "^5.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/types": { + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz", + "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.5", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@leanstacks/lambda-utils": { + "version": "0.3.0-alpha.4", + "resolved": "https://registry.npmjs.org/@leanstacks/lambda-utils/-/lambda-utils-0.3.0-alpha.4.tgz", + "integrity": "sha512-RUs2RkhEr7djdQy5EjhWDHLpyCsxmc/P4p6tBMPQZE5KVTzebRFRiXKh2MGZJ5teOjeV8Xtwa7Fi2h2STujXDw==", + "license": "MIT", + "dependencies": { + "@aws-sdk/client-dynamodb": "3.955.0", + "@aws-sdk/lib-dynamodb": "3.955.0", + "pino": "10.1.0", + "pino-lambda": "4.4.1", + "zod": "4.2.1" + } + }, + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/client-dynamodb": { + "version": "3.955.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.955.0.tgz", + "integrity": "sha512-Qo1Sv6rKxRCecaKOsdjwbeYvnmlVyueaNP5/DmAzdbxVI7pGsIFUqCXQYA0jwfONwoMoMwf/PsyGaW/+9nGhhQ==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.954.0", + "@aws-sdk/credential-provider-node": "3.955.0", + "@aws-sdk/dynamodb-codec": "3.954.0", + "@aws-sdk/middleware-endpoint-discovery": "3.953.0", + "@aws-sdk/middleware-host-header": "3.953.0", + "@aws-sdk/middleware-logger": "3.953.0", + "@aws-sdk/middleware-recursion-detection": "3.953.0", + "@aws-sdk/middleware-user-agent": "3.954.0", + "@aws-sdk/region-config-resolver": "3.953.0", + "@aws-sdk/types": "3.953.0", + "@aws-sdk/util-endpoints": "3.953.0", + "@aws-sdk/util-user-agent-browser": "3.953.0", + "@aws-sdk/util-user-agent-node": "3.954.0", + "@smithy/config-resolver": "^4.4.4", + "@smithy/core": "^3.19.0", + "@smithy/fetch-http-handler": "^5.3.7", + "@smithy/hash-node": "^4.2.6", + "@smithy/invalid-dependency": "^4.2.6", + "@smithy/middleware-content-length": "^4.2.6", + "@smithy/middleware-endpoint": "^4.4.0", + "@smithy/middleware-retry": "^4.4.16", + "@smithy/middleware-serde": "^4.2.7", + "@smithy/middleware-stack": "^4.2.6", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/node-http-handler": "^4.4.6", + "@smithy/protocol-http": "^5.3.6", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", + "@smithy/url-parser": "^4.2.6", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.15", + "@smithy/util-defaults-mode-node": "^4.2.18", + "@smithy/util-endpoints": "^3.2.6", + "@smithy/util-middleware": "^4.2.6", + "@smithy/util-retry": "^4.2.6", + "@smithy/util-utf8": "^4.2.0", + "@smithy/util-waiter": "^4.2.6", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/client-sso": { + "version": "3.955.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.955.0.tgz", + "integrity": "sha512-+nym5boDFt2ksba0fElocMKxCFJbJcd31PI3502hoI1N5VK7HyxkQeBtQJ64JYomvw8eARjWWC13hkB0LtZILw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.954.0", + "@aws-sdk/middleware-host-header": "3.953.0", + "@aws-sdk/middleware-logger": "3.953.0", + "@aws-sdk/middleware-recursion-detection": "3.953.0", + "@aws-sdk/middleware-user-agent": "3.954.0", + "@aws-sdk/region-config-resolver": "3.953.0", + "@aws-sdk/types": "3.953.0", + "@aws-sdk/util-endpoints": "3.953.0", + "@aws-sdk/util-user-agent-browser": "3.953.0", + "@aws-sdk/util-user-agent-node": "3.954.0", + "@smithy/config-resolver": "^4.4.4", + "@smithy/core": "^3.19.0", + "@smithy/fetch-http-handler": "^5.3.7", + "@smithy/hash-node": "^4.2.6", + "@smithy/invalid-dependency": "^4.2.6", + "@smithy/middleware-content-length": "^4.2.6", + "@smithy/middleware-endpoint": "^4.4.0", + "@smithy/middleware-retry": "^4.4.16", + "@smithy/middleware-serde": "^4.2.7", + "@smithy/middleware-stack": "^4.2.6", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/node-http-handler": "^4.4.6", + "@smithy/protocol-http": "^5.3.6", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", + "@smithy/url-parser": "^4.2.6", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.15", + "@smithy/util-defaults-mode-node": "^4.2.18", + "@smithy/util-endpoints": "^3.2.6", + "@smithy/util-middleware": "^4.2.6", + "@smithy/util-retry": "^4.2.6", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/core": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.954.0.tgz", + "integrity": "sha512-5oYO5RP+mvCNXNj8XnF9jZo0EP0LTseYOJVNQYcii1D9DJqzHL3HJWurYh7cXxz7G7eDyvVYA01O9Xpt34TdoA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.953.0", + "@aws-sdk/xml-builder": "3.953.0", + "@smithy/core": "^3.19.0", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/property-provider": "^4.2.6", + "@smithy/protocol-http": "^5.3.6", + "@smithy/signature-v4": "^5.3.6", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-middleware": "^4.2.6", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/credential-provider-env": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.954.0.tgz", + "integrity": "sha512-2HNkqBjfsvyoRuPAiFh86JBFMFyaCNhL4VyH6XqwTGKZffjG7hdBmzXPy7AT7G3oFh1k/1Zc27v0qxaKoK7mBA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@smithy/property-provider": "^4.2.6", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/credential-provider-http": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.954.0.tgz", + "integrity": "sha512-CrWD5300+NE1OYRnSVDxoG7G0b5cLIZb7yp+rNQ5Jq/kqnTmyJXpVAsivq+bQIDaGzPXhadzpAMIoo7K/aHaag==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@smithy/fetch-http-handler": "^5.3.7", + "@smithy/node-http-handler": "^4.4.6", + "@smithy/property-provider": "^4.2.6", + "@smithy/protocol-http": "^5.3.6", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", + "@smithy/util-stream": "^4.5.7", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.955.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.955.0.tgz", + "integrity": "sha512-90isLovxsPzaaSx3IIUZuxym6VXrsRetnQ3AuHr2kiTFk2pIzyIwmi+gDcUaLXQ5nNBoSj1Z/4+i1vhxa1n2DQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@aws-sdk/credential-provider-env": "3.954.0", + "@aws-sdk/credential-provider-http": "3.954.0", + "@aws-sdk/credential-provider-login": "3.955.0", + "@aws-sdk/credential-provider-process": "3.954.0", + "@aws-sdk/credential-provider-sso": "3.955.0", + "@aws-sdk/credential-provider-web-identity": "3.955.0", + "@aws-sdk/nested-clients": "3.955.0", + "@aws-sdk/types": "3.953.0", + "@smithy/credential-provider-imds": "^4.2.6", + "@smithy/property-provider": "^4.2.6", + "@smithy/shared-ini-file-loader": "^4.4.1", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/credential-provider-login": { + "version": "3.955.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.955.0.tgz", + "integrity": "sha512-xlkmSvg8oDN5LIxLAq3N1QWK8F8gUAsBWZlp1IX8Lr5XhcKI3GVarIIUcZrvCy1NjzCd/LDXYdNL6MRlNP4bAw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@aws-sdk/nested-clients": "3.955.0", + "@aws-sdk/types": "3.953.0", + "@smithy/property-provider": "^4.2.6", + "@smithy/protocol-http": "^5.3.6", + "@smithy/shared-ini-file-loader": "^4.4.1", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/credential-provider-node": { + "version": "3.955.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.955.0.tgz", + "integrity": "sha512-XIL4QB+dPOJA6DRTmYZL52wFcLTslb7V1ydS4FCNT2DVLhkO4ExkPP+pe5YmIpzt/Our1ugS+XxAs3e6BtyFjA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.954.0", + "@aws-sdk/credential-provider-http": "3.954.0", + "@aws-sdk/credential-provider-ini": "3.955.0", + "@aws-sdk/credential-provider-process": "3.954.0", + "@aws-sdk/credential-provider-sso": "3.955.0", + "@aws-sdk/credential-provider-web-identity": "3.955.0", + "@aws-sdk/types": "3.953.0", + "@smithy/credential-provider-imds": "^4.2.6", + "@smithy/property-provider": "^4.2.6", + "@smithy/shared-ini-file-loader": "^4.4.1", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/credential-provider-process": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.954.0.tgz", + "integrity": "sha512-Y1/0O2LgbKM8iIgcVj/GNEQW6p90LVTCOzF2CI1pouoKqxmZ/1F7F66WHoa6XUOfKaCRj/R6nuMR3om9ThaM5A==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@smithy/property-provider": "^4.2.6", + "@smithy/shared-ini-file-loader": "^4.4.1", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.955.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.955.0.tgz", + "integrity": "sha512-Y99KI73Fn8JnB4RY5Ls6j7rd5jmFFwnY9WLHIWeJdc+vfwL6Bb1uWKW3+m/B9+RC4Xoz2nQgtefBcdWq5Xx8iw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/client-sso": "3.955.0", + "@aws-sdk/core": "3.954.0", + "@aws-sdk/token-providers": "3.955.0", + "@aws-sdk/types": "3.953.0", + "@smithy/property-provider": "^4.2.6", + "@smithy/shared-ini-file-loader": "^4.4.1", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.955.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.955.0.tgz", + "integrity": "sha512-+lFxkZ2Vz3qp/T68ZONKzWVTQvomTu7E6tts1dfAbEcDt62Y/nPCByq/C2hQj+TiN05HrUx+yTJaGHBklhkbqA==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@aws-sdk/nested-clients": "3.955.0", + "@aws-sdk/types": "3.953.0", + "@smithy/property-provider": "^4.2.6", + "@smithy/shared-ini-file-loader": "^4.4.1", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/dynamodb-codec": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/dynamodb-codec/-/dynamodb-codec-3.954.0.tgz", + "integrity": "sha512-fNY0L1l9e36pLJef4NY5k7Q1SJnm5rgLSxSRPT8xL+bhQBtEn2E2t4JdBiTqlxgeyuOrafWOawbg8yS3pRPcLw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@smithy/core": "^3.19.0", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", + "@smithy/util-base64": "^4.3.0", + "tslib": "^2.6.2" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-dynamodb": "^3.954.0" } }, - "node_modules/@jest/types": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz", - "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", - "dev": true, - "license": "MIT", + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/lib-dynamodb": { + "version": "3.955.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.955.0.tgz", + "integrity": "sha512-THm4It0gSWTQZDK+I7J/D1FmoNGXDHRpeYrnJ1uYx2z4TSWc8qqqHN2L/x3W8HtRITMUNUolCZI4tIz9zxdOow==", + "license": "Apache-2.0", "dependencies": { - "@jest/pattern": "30.0.1", - "@jest/schemas": "30.0.5", - "@types/istanbul-lib-coverage": "^2.0.6", - "@types/istanbul-reports": "^3.0.4", - "@types/node": "*", - "@types/yargs": "^17.0.33", - "chalk": "^4.1.2" + "@aws-sdk/core": "3.954.0", + "@aws-sdk/util-dynamodb": "3.955.0", + "@smithy/core": "^3.19.0", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-dynamodb": "^3.955.0" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "license": "MIT", + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.954.0.tgz", + "integrity": "sha512-5PX8JDe3dB2+MqXeGIhmgFnm2rbVsSxhz+Xyuu1oxLtbOn+a9UDA+sNBufEBjt3UxWy5qwEEY1fxdbXXayjlGg==", + "license": "Apache-2.0", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" + "@aws-sdk/core": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@aws-sdk/util-endpoints": "3.953.0", + "@smithy/core": "^3.19.0", + "@smithy/protocol-http": "^5.3.6", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "license": "MIT", + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/nested-clients": { + "version": "3.955.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.955.0.tgz", + "integrity": "sha512-RBi6CQHbPF09kqXAoiEOOPkVnSoU5YppKoOt/cgsWfoMHwC+7itIrEv+yRD62h14jIjF3KngVIQIrBRbX3o3/Q==", + "license": "Apache-2.0", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.954.0", + "@aws-sdk/middleware-host-header": "3.953.0", + "@aws-sdk/middleware-logger": "3.953.0", + "@aws-sdk/middleware-recursion-detection": "3.953.0", + "@aws-sdk/middleware-user-agent": "3.954.0", + "@aws-sdk/region-config-resolver": "3.953.0", + "@aws-sdk/types": "3.953.0", + "@aws-sdk/util-endpoints": "3.953.0", + "@aws-sdk/util-user-agent-browser": "3.953.0", + "@aws-sdk/util-user-agent-node": "3.954.0", + "@smithy/config-resolver": "^4.4.4", + "@smithy/core": "^3.19.0", + "@smithy/fetch-http-handler": "^5.3.7", + "@smithy/hash-node": "^4.2.6", + "@smithy/invalid-dependency": "^4.2.6", + "@smithy/middleware-content-length": "^4.2.6", + "@smithy/middleware-endpoint": "^4.4.0", + "@smithy/middleware-retry": "^4.4.16", + "@smithy/middleware-serde": "^4.2.7", + "@smithy/middleware-stack": "^4.2.6", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/node-http-handler": "^4.4.6", + "@smithy/protocol-http": "^5.3.6", + "@smithy/smithy-client": "^4.10.1", + "@smithy/types": "^4.10.0", + "@smithy/url-parser": "^4.2.6", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.15", + "@smithy/util-defaults-mode-node": "^4.2.18", + "@smithy/util-endpoints": "^3.2.6", + "@smithy/util-middleware": "^4.2.6", + "@smithy/util-retry": "^4.2.6", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" } }, - "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==", - "dev": true, - "license": "MIT", + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/token-providers": { + "version": "3.955.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.955.0.tgz", + "integrity": "sha512-LVpWkxXvMPgZofP2Gc8XBfQhsyecBMVARDHWMvks6vPbCLSTM7dw6H1HI9qbGNCurYcyc2xBRAkEDhChQlbPPg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.954.0", + "@aws-sdk/nested-clients": "3.955.0", + "@aws-sdk/types": "3.953.0", + "@smithy/property-provider": "^4.2.6", + "@smithy/shared-ini-file-loader": "^4.4.1", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">=6.0.0" + "node": ">=18.0.0" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "license": "MIT", + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/util-dynamodb": { + "version": "3.955.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.955.0.tgz", + "integrity": "sha512-X/gSn2fIv9G5JshUzuZmAp30C5IhjdZpfsF/5476wDDse7GnqIe8SfH7Q4MVFcdd08fTT9nPFETEnMc8ga5WHg==", + "license": "Apache-2.0", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-dynamodb": "^3.955.0" } }, - "node_modules/@leanstacks/lambda-utils": { - "version": "0.2.0-alpha.3", - "resolved": "https://registry.npmjs.org/@leanstacks/lambda-utils/-/lambda-utils-0.2.0-alpha.3.tgz", - "integrity": "sha512-ZFCvUgzdqxzfQLepbg44GCLNI64BokoA6a4pjhQvLoFZeIxsOQo/oZCetu6XPde67D5eDcKyUgBHtveS3KW+4A==", - "license": "MIT", + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.954.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.954.0.tgz", + "integrity": "sha512-fB5S5VOu7OFkeNzcblQlez4AjO5hgDFaa7phYt7716YWisY3RjAaQPlxgv+G3GltHHDJIfzEC5aRxdf62B9zMg==", + "license": "Apache-2.0", "dependencies": { - "pino": "10.1.0", - "pino-lambda": "4.4.1" + "@aws-sdk/middleware-user-agent": "3.954.0", + "@aws-sdk/types": "3.953.0", + "@smithy/node-config-provider": "^4.3.6", + "@smithy/types": "^4.10.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } } }, "node_modules/@napi-rs/wasm-runtime": { @@ -2355,12 +3520,12 @@ } }, "node_modules/@smithy/abort-controller": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.6.tgz", - "integrity": "sha512-P7JD4J+wxHMpGxqIg6SHno2tPkZbBUBLbPpR5/T1DEUvw/mEaINBMaPFZNM7lA+ToSCZ36j6nMHa+5kej+fhGg==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.7.tgz", + "integrity": "sha512-rzMY6CaKx2qxrbYbqjXWS0plqEy7LOdKHS0bg4ixJ6aoGDPNUcLWk/FRNuCILh7GKLG9TFUXYYeQQldMBBwuyw==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.10.0", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -2368,16 +3533,16 @@ } }, "node_modules/@smithy/config-resolver": { - "version": "4.4.4", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.4.tgz", - "integrity": "sha512-s3U5ChS21DwU54kMmZ0UJumoS5cg0+rGVZvN6f5Lp6EbAVi0ZyP+qDSHdewfmXKUgNK1j3z45JyzulkDukrjAA==", + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.5.tgz", + "integrity": "sha512-HAGoUAFYsUkoSckuKbCPayECeMim8pOu+yLy1zOxt1sifzEbrsRpYa+mKcMdiHKMeiqOibyPG0sFJnmaV/OGEg==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.3.6", - "@smithy/types": "^4.10.0", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/types": "^4.11.0", "@smithy/util-config-provider": "^4.2.0", - "@smithy/util-endpoints": "^3.2.6", - "@smithy/util-middleware": "^4.2.6", + "@smithy/util-endpoints": "^3.2.7", + "@smithy/util-middleware": "^4.2.7", "tslib": "^2.6.2" }, "engines": { @@ -2385,18 +3550,18 @@ } }, "node_modules/@smithy/core": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.19.0.tgz", - "integrity": "sha512-Y9oHXpBcXQgYHOcAEmxjkDilUbSTkgKjoHYed3WaYUH8jngq8lPWDBSpjHblJ9uOgBdy5mh3pzebrScDdYr29w==", + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.20.0.tgz", + "integrity": "sha512-WsSHCPq/neD5G/MkK4csLI5Y5Pkd9c1NMfpYEKeghSGaD4Ja1qLIohRQf2D5c1Uy5aXp76DeKHkzWZ9KAlHroQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/middleware-serde": "^4.2.7", - "@smithy/protocol-http": "^5.3.6", - "@smithy/types": "^4.10.0", + "@smithy/middleware-serde": "^4.2.8", + "@smithy/protocol-http": "^5.3.7", + "@smithy/types": "^4.11.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-middleware": "^4.2.6", - "@smithy/util-stream": "^4.5.7", + "@smithy/util-middleware": "^4.2.7", + "@smithy/util-stream": "^4.5.8", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" @@ -2406,15 +3571,15 @@ } }, "node_modules/@smithy/credential-provider-imds": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.6.tgz", - "integrity": "sha512-xBmawExyTzOjbhzkZwg+vVm/khg28kG+rj2sbGlULjFd1jI70sv/cbpaR0Ev4Yfd6CpDUDRMe64cTqR//wAOyA==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.7.tgz", + "integrity": "sha512-CmduWdCiILCRNbQWFR0OcZlUPVtyE49Sr8yYL0rZQ4D/wKxiNzBNS/YHemvnbkIWj623fplgkexUd/c9CAKdoA==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.3.6", - "@smithy/property-provider": "^4.2.6", - "@smithy/types": "^4.10.0", - "@smithy/url-parser": "^4.2.6", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/property-provider": "^4.2.7", + "@smithy/types": "^4.11.0", + "@smithy/url-parser": "^4.2.7", "tslib": "^2.6.2" }, "engines": { @@ -2422,13 +3587,13 @@ } }, "node_modules/@smithy/eventstream-codec": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.2.6.tgz", - "integrity": "sha512-OZfsI+YRG26XZik/jKMMg37acnBSbUiK/8nETW3uM3mLj+0tMmFXdHQw1e5WEd/IHN8BGOh3te91SNDe2o4RHg==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.2.7.tgz", + "integrity": "sha512-DrpkEoM3j9cBBWhufqBwnbbn+3nf1N9FP6xuVJ+e220jbactKuQgaZwjwP5CP1t+O94brm2JgVMD2atMGX3xIQ==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/crc32": "5.2.0", - "@smithy/types": "^4.10.0", + "@smithy/types": "^4.11.0", "@smithy/util-hex-encoding": "^4.2.0", "tslib": "^2.6.2" }, @@ -2437,13 +3602,13 @@ } }, "node_modules/@smithy/eventstream-serde-browser": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.2.6.tgz", - "integrity": "sha512-6OiaAaEbLB6dEkRbQyNzFSJv5HDvly3Mc6q/qcPd2uS/g3szR8wAIkh7UndAFKfMypNSTuZ6eCBmgCLR5LacTg==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.2.7.tgz", + "integrity": "sha512-ujzPk8seYoDBmABDE5YqlhQZAXLOrtxtJLrbhHMKjBoG5b4dK4i6/mEU+6/7yXIAkqOO8sJ6YxZl+h0QQ1IJ7g==", "license": "Apache-2.0", "dependencies": { - "@smithy/eventstream-serde-universal": "^4.2.6", - "@smithy/types": "^4.10.0", + "@smithy/eventstream-serde-universal": "^4.2.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -2451,12 +3616,12 @@ } }, "node_modules/@smithy/eventstream-serde-config-resolver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.3.6.tgz", - "integrity": "sha512-xP5YXbOVRVN8A4pDnSUkEUsL9fYFU6VNhxo8tgr13YnMbf3Pn4xVr+hSyLVjS1Frfi1Uk03ET5Bwml4+0CeYEw==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.3.7.tgz", + "integrity": "sha512-x7BtAiIPSaNaWuzm24Q/mtSkv+BrISO/fmheiJ39PKRNH3RmH2Hph/bUKSOBOBC9unqfIYDhKTHwpyZycLGPVQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.10.0", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -2464,13 +3629,13 @@ } }, "node_modules/@smithy/eventstream-serde-node": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.2.6.tgz", - "integrity": "sha512-jhH7nJuaOpnTFcuZpWK9dqb6Ge2yGi1okTo0W6wkJrfwAm2vwmO74tF1v07JmrSyHBcKLQATEexclJw9K1Vj7w==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.2.7.tgz", + "integrity": "sha512-roySCtHC5+pQq5lK4be1fZ/WR6s/AxnPaLfCODIPArtN2du8s5Ot4mKVK3pPtijL/L654ws592JHJ1PbZFF6+A==", "license": "Apache-2.0", "dependencies": { - "@smithy/eventstream-serde-universal": "^4.2.6", - "@smithy/types": "^4.10.0", + "@smithy/eventstream-serde-universal": "^4.2.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -2478,13 +3643,13 @@ } }, "node_modules/@smithy/eventstream-serde-universal": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.2.6.tgz", - "integrity": "sha512-olIfZ230B64TvPD6b0tPvrEp2eB0FkyL3KvDlqF4RVmIc/kn3orzXnV6DTQdOOW5UU+M5zKY3/BU47X420/oPw==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.2.7.tgz", + "integrity": "sha512-QVD+g3+icFkThoy4r8wVFZMsIP08taHVKjE6Jpmz8h5CgX/kk6pTODq5cht0OMtcapUx+xrPzUTQdA+TmO0m1g==", "license": "Apache-2.0", "dependencies": { - "@smithy/eventstream-codec": "^4.2.6", - "@smithy/types": "^4.10.0", + "@smithy/eventstream-codec": "^4.2.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -2492,14 +3657,14 @@ } }, "node_modules/@smithy/fetch-http-handler": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.7.tgz", - "integrity": "sha512-fcVap4QwqmzQwQK9QU3keeEpCzTjnP9NJ171vI7GnD7nbkAIcP9biZhDUx88uRH9BabSsQDS0unUps88uZvFIQ==", + "version": "5.3.8", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.8.tgz", + "integrity": "sha512-h/Fi+o7mti4n8wx1SR6UHWLaakwHRx29sizvp8OOm7iqwKGFneT06GCSFhml6Bha5BT6ot5pj3CYZnCHhGC2Rg==", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.3.6", - "@smithy/querystring-builder": "^4.2.6", - "@smithy/types": "^4.10.0", + "@smithy/protocol-http": "^5.3.7", + "@smithy/querystring-builder": "^4.2.7", + "@smithy/types": "^4.11.0", "@smithy/util-base64": "^4.3.0", "tslib": "^2.6.2" }, @@ -2508,12 +3673,12 @@ } }, "node_modules/@smithy/hash-node": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.6.tgz", - "integrity": "sha512-k3Dy9VNR37wfMh2/1RHkFf/e0rMyN0pjY0FdyY6ItJRjENYyVPRMwad6ZR1S9HFm6tTuIOd9pqKBmtJ4VHxvxg==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.7.tgz", + "integrity": "sha512-PU/JWLTBCV1c8FtB8tEFnY4eV1tSfBc7bDBADHfn1K+uRbPgSJ9jnJp0hyjiFN2PMdPzxsf1Fdu0eo9fJ760Xw==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.10.0", + "@smithy/types": "^4.11.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" @@ -2523,12 +3688,12 @@ } }, "node_modules/@smithy/invalid-dependency": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.6.tgz", - "integrity": "sha512-E4t/V/q2T46RY21fpfznd1iSLTvCXKNKo4zJ1QuEFN4SE9gKfu2vb6bgq35LpufkQ+SETWIC7ZAf2GGvTlBaMQ==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.7.tgz", + "integrity": "sha512-ncvgCr9a15nPlkhIUx3CU4d7E7WEuVJOV7fS7nnK2hLtPK9tYRBkMHQbhXU1VvvKeBm/O0x26OEoBq+ngFpOEQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.10.0", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -2548,13 +3713,13 @@ } }, "node_modules/@smithy/middleware-content-length": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.6.tgz", - "integrity": "sha512-0cjqjyfj+Gls30ntq45SsBtqF3dfJQCeqQPyGz58Pk8OgrAr5YiB7ZvDzjCA94p4r6DCI4qLm7FKobqBjf515w==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.7.tgz", + "integrity": "sha512-GszfBfCcvt7kIbJ41LuNa5f0wvQCHhnGx/aDaZJCCT05Ld6x6U2s0xsc/0mBFONBZjQJp2U/0uSJ178OXOwbhg==", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.3.6", - "@smithy/types": "^4.10.0", + "@smithy/protocol-http": "^5.3.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -2562,18 +3727,18 @@ } }, "node_modules/@smithy/middleware-endpoint": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.0.tgz", - "integrity": "sha512-M6qWfUNny6NFNy8amrCGIb9TfOMUkHVtg9bHtEFGRgfH7A7AtPpn/fcrToGPjVDK1ECuMVvqGQOXcZxmu9K+7A==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.1.tgz", + "integrity": "sha512-gpLspUAoe6f1M6H0u4cVuFzxZBrsGZmjx2O9SigurTx4PbntYa4AJ+o0G0oGm1L2oSX6oBhcGHwrfJHup2JnJg==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.19.0", - "@smithy/middleware-serde": "^4.2.7", - "@smithy/node-config-provider": "^4.3.6", - "@smithy/shared-ini-file-loader": "^4.4.1", - "@smithy/types": "^4.10.0", - "@smithy/url-parser": "^4.2.6", - "@smithy/util-middleware": "^4.2.6", + "@smithy/core": "^3.20.0", + "@smithy/middleware-serde": "^4.2.8", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/shared-ini-file-loader": "^4.4.2", + "@smithy/types": "^4.11.0", + "@smithy/url-parser": "^4.2.7", + "@smithy/util-middleware": "^4.2.7", "tslib": "^2.6.2" }, "engines": { @@ -2581,18 +3746,18 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "4.4.16", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.16.tgz", - "integrity": "sha512-XPpNhNRzm3vhYm7YCsyw3AtmWggJbg1wNGAoqb7NBYr5XA5isMRv14jgbYyUV6IvbTBFZQdf2QpeW43LrRdStQ==", + "version": "4.4.17", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.17.tgz", + "integrity": "sha512-MqbXK6Y9uq17h+4r0ogu/sBT6V/rdV+5NvYL7ZV444BKfQygYe8wAhDrVXagVebN6w2RE0Fm245l69mOsPGZzg==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.3.6", - "@smithy/protocol-http": "^5.3.6", - "@smithy/service-error-classification": "^4.2.6", - "@smithy/smithy-client": "^4.10.1", - "@smithy/types": "^4.10.0", - "@smithy/util-middleware": "^4.2.6", - "@smithy/util-retry": "^4.2.6", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/protocol-http": "^5.3.7", + "@smithy/service-error-classification": "^4.2.7", + "@smithy/smithy-client": "^4.10.2", + "@smithy/types": "^4.11.0", + "@smithy/util-middleware": "^4.2.7", + "@smithy/util-retry": "^4.2.7", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" }, @@ -2601,13 +3766,13 @@ } }, "node_modules/@smithy/middleware-serde": { - "version": "4.2.7", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.7.tgz", - "integrity": "sha512-PFMVHVPgtFECeu4iZ+4SX6VOQT0+dIpm4jSPLLL6JLSkp9RohGqKBKD0cbiXdeIFS08Forp0UHI6kc0gIHenSA==", + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.8.tgz", + "integrity": "sha512-8rDGYen5m5+NV9eHv9ry0sqm2gI6W7mc1VSFMtn6Igo25S507/HaOX9LTHAS2/J32VXD0xSzrY0H5FJtOMS4/w==", "license": "Apache-2.0", "dependencies": { - "@smithy/protocol-http": "^5.3.6", - "@smithy/types": "^4.10.0", + "@smithy/protocol-http": "^5.3.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -2615,12 +3780,12 @@ } }, "node_modules/@smithy/middleware-stack": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.6.tgz", - "integrity": "sha512-JSbALU3G+JS4kyBZPqnJ3hxIYwOVRV7r9GNQMS6j5VsQDo5+Es5nddLfr9TQlxZLNHPvKSh+XSB0OuWGfSWFcA==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.7.tgz", + "integrity": "sha512-bsOT0rJ+HHlZd9crHoS37mt8qRRN/h9jRve1SXUhVbkRzu0QaNYZp1i1jha4n098tsvROjcwfLlfvcFuJSXEsw==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.10.0", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -2628,14 +3793,14 @@ } }, "node_modules/@smithy/node-config-provider": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.6.tgz", - "integrity": "sha512-fYEyL59Qe82Ha1p97YQTMEQPJYmBS+ux76foqluaTVWoG9Px5J53w6NvXZNE3wP7lIicLDF7Vj1Em18XTX7fsA==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.7.tgz", + "integrity": "sha512-7r58wq8sdOcrwWe+klL9y3bc4GW1gnlfnFOuL7CXa7UzfhzhxKuzNdtqgzmTV+53lEp9NXh5hY/S4UgjLOzPfw==", "license": "Apache-2.0", "dependencies": { - "@smithy/property-provider": "^4.2.6", - "@smithy/shared-ini-file-loader": "^4.4.1", - "@smithy/types": "^4.10.0", + "@smithy/property-provider": "^4.2.7", + "@smithy/shared-ini-file-loader": "^4.4.2", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -2643,15 +3808,15 @@ } }, "node_modules/@smithy/node-http-handler": { - "version": "4.4.6", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.6.tgz", - "integrity": "sha512-Gsb9jf4ido5BhPfani4ggyrKDd3ZK+vTFWmUaZeFg5G3E5nhFmqiTzAIbHqmPs1sARuJawDiGMGR/nY+Gw6+aQ==", + "version": "4.4.7", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.7.tgz", + "integrity": "sha512-NELpdmBOO6EpZtWgQiHjoShs1kmweaiNuETUpuup+cmm/xJYjT4eUjfhrXRP4jCOaAsS3c3yPsP3B+K+/fyPCQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/abort-controller": "^4.2.6", - "@smithy/protocol-http": "^5.3.6", - "@smithy/querystring-builder": "^4.2.6", - "@smithy/types": "^4.10.0", + "@smithy/abort-controller": "^4.2.7", + "@smithy/protocol-http": "^5.3.7", + "@smithy/querystring-builder": "^4.2.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -2659,12 +3824,12 @@ } }, "node_modules/@smithy/property-provider": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.6.tgz", - "integrity": "sha512-a/tGSLPtaia2krbRdwR4xbZKO8lU67DjMk/jfY4QKt4PRlKML+2tL/gmAuhNdFDioO6wOq0sXkfnddNFH9mNUA==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.7.tgz", + "integrity": "sha512-jmNYKe9MGGPoSl/D7JDDs1C8b3dC8f/w78LbaVfoTtWy4xAd5dfjaFG9c9PWPihY4ggMQNQSMtzU77CNgAJwmA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.10.0", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -2672,12 +3837,12 @@ } }, "node_modules/@smithy/protocol-http": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.6.tgz", - "integrity": "sha512-qLRZzP2+PqhE3OSwvY2jpBbP0WKTZ9opTsn+6IWYI0SKVpbG+imcfNxXPq9fj5XeaUTr7odpsNpK6dmoiM1gJQ==", + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.7.tgz", + "integrity": "sha512-1r07pb994I20dD/c2seaZhoCuNYm0rWrvBxhCQ70brNh11M5Ml2ew6qJVo0lclB3jMIXirD4s2XRXRe7QEi0xA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.10.0", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -2685,12 +3850,12 @@ } }, "node_modules/@smithy/querystring-builder": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.6.tgz", - "integrity": "sha512-MeM9fTAiD3HvoInK/aA8mgJaKQDvm8N0dKy6EiFaCfgpovQr4CaOkJC28XqlSRABM+sHdSQXbC8NZ0DShBMHqg==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.7.tgz", + "integrity": "sha512-eKONSywHZxK4tBxe2lXEysh8wbBdvDWiA+RIuaxZSgCMmA0zMgoDpGLJhnyj+c0leOQprVnXOmcB4m+W9Rw7sg==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.10.0", + "@smithy/types": "^4.11.0", "@smithy/util-uri-escape": "^4.2.0", "tslib": "^2.6.2" }, @@ -2699,12 +3864,12 @@ } }, "node_modules/@smithy/querystring-parser": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.6.tgz", - "integrity": "sha512-YmWxl32SQRw/kIRccSOxzS/Ib8/b5/f9ex0r5PR40jRJg8X1wgM3KrR2In+8zvOGVhRSXgvyQpw9yOSlmfmSnA==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.7.tgz", + "integrity": "sha512-3X5ZvzUHmlSTHAXFlswrS6EGt8fMSIxX/c3Rm1Pni3+wYWB6cjGocmRIoqcQF9nU5OgGmL0u7l9m44tSUpfj9w==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.10.0", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -2712,24 +3877,24 @@ } }, "node_modules/@smithy/service-error-classification": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.6.tgz", - "integrity": "sha512-Q73XBrzJlGTut2nf5RglSntHKgAG0+KiTJdO5QQblLfr4TdliGwIAha1iZIjwisc3rA5ulzqwwsYC6xrclxVQg==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.7.tgz", + "integrity": "sha512-YB7oCbukqEb2Dlh3340/8g8vNGbs/QsNNRms+gv3N2AtZz9/1vSBx6/6tpwQpZMEJFs7Uq8h4mmOn48ZZ72MkA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.10.0" + "@smithy/types": "^4.11.0" }, "engines": { "node": ">=18.0.0" } }, "node_modules/@smithy/shared-ini-file-loader": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.1.tgz", - "integrity": "sha512-tph+oQYPbpN6NamF030hx1gb5YN2Plog+GLaRHpoEDwp8+ZPG26rIJvStG9hkWzN2HBn3HcWg0sHeB0tmkYzqA==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.2.tgz", + "integrity": "sha512-M7iUUff/KwfNunmrgtqBfvZSzh3bmFgv/j/t1Y1dQ+8dNo34br1cqVEqy6v0mYEgi0DkGO7Xig0AnuOaEGVlcg==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.10.0", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -2737,16 +3902,16 @@ } }, "node_modules/@smithy/signature-v4": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.6.tgz", - "integrity": "sha512-P1TXDHuQMadTMTOBv4oElZMURU4uyEhxhHfn+qOc2iofW9Rd4sZtBGx58Lzk112rIGVEYZT8eUMK4NftpewpRA==", + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.7.tgz", + "integrity": "sha512-9oNUlqBlFZFOSdxgImA6X5GFuzE7V2H7VG/7E70cdLhidFbdtvxxt81EHgykGK5vq5D3FafH//X+Oy31j3CKOg==", "license": "Apache-2.0", "dependencies": { "@smithy/is-array-buffer": "^4.2.0", - "@smithy/protocol-http": "^5.3.6", - "@smithy/types": "^4.10.0", + "@smithy/protocol-http": "^5.3.7", + "@smithy/types": "^4.11.0", "@smithy/util-hex-encoding": "^4.2.0", - "@smithy/util-middleware": "^4.2.6", + "@smithy/util-middleware": "^4.2.7", "@smithy/util-uri-escape": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" @@ -2756,17 +3921,17 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.10.1.tgz", - "integrity": "sha512-1ovWdxzYprhq+mWqiGZlt3kF69LJthuQcfY9BIyHx9MywTFKzFapluku1QXoaBB43GCsLDxNqS+1v30ure69AA==", + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.10.2.tgz", + "integrity": "sha512-D5z79xQWpgrGpAHb054Fn2CCTQZpog7JELbVQ6XAvXs5MNKWf28U9gzSBlJkOyMl9LA1TZEjRtwvGXfP0Sl90g==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.19.0", - "@smithy/middleware-endpoint": "^4.4.0", - "@smithy/middleware-stack": "^4.2.6", - "@smithy/protocol-http": "^5.3.6", - "@smithy/types": "^4.10.0", - "@smithy/util-stream": "^4.5.7", + "@smithy/core": "^3.20.0", + "@smithy/middleware-endpoint": "^4.4.1", + "@smithy/middleware-stack": "^4.2.7", + "@smithy/protocol-http": "^5.3.7", + "@smithy/types": "^4.11.0", + "@smithy/util-stream": "^4.5.8", "tslib": "^2.6.2" }, "engines": { @@ -2774,9 +3939,9 @@ } }, "node_modules/@smithy/types": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.10.0.tgz", - "integrity": "sha512-K9mY7V/f3Ul+/Gz4LJANZ3vJ/yiBIwCyxe0sPT4vNJK63Srvd+Yk1IzP0t+nE7XFSpIGtzR71yljtnqpUTYFlQ==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.11.0.tgz", + "integrity": "sha512-mlrmL0DRDVe3mNrjTcVcZEgkFmufITfUAPBEA+AHYiIeYyJebso/He1qLbP3PssRe22KUzLRpQSdBPbXdgZ2VA==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -2786,13 +3951,13 @@ } }, "node_modules/@smithy/url-parser": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.6.tgz", - "integrity": "sha512-tVoyzJ2vXp4R3/aeV4EQjBDmCuWxRa8eo3KybL7Xv4wEM16nObYh7H1sNfcuLWHAAAzb0RVyxUz1S3sGj4X+Tg==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.7.tgz", + "integrity": "sha512-/RLtVsRV4uY3qPWhBDsjwahAtt3x2IsMGnP5W1b2VZIe+qgCqkLxI1UOHDZp1Q1QSOrdOR32MF3Ph2JfWT1VHg==", "license": "Apache-2.0", "dependencies": { - "@smithy/querystring-parser": "^4.2.6", - "@smithy/types": "^4.10.0", + "@smithy/querystring-parser": "^4.2.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -2863,14 +4028,14 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.3.15", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.15.tgz", - "integrity": "sha512-LiZQVAg/oO8kueX4c+oMls5njaD2cRLXRfcjlTYjhIqmwHnCwkQO5B3dMQH0c5PACILxGAQf6Mxsq7CjlDc76A==", + "version": "4.3.16", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.16.tgz", + "integrity": "sha512-/eiSP3mzY3TsvUOYMeL4EqUX6fgUOj2eUOU4rMMgVbq67TiRLyxT7Xsjxq0bW3OwuzK009qOwF0L2OgJqperAQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/property-provider": "^4.2.6", - "@smithy/smithy-client": "^4.10.1", - "@smithy/types": "^4.10.0", + "@smithy/property-provider": "^4.2.7", + "@smithy/smithy-client": "^4.10.2", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -2878,17 +4043,17 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.2.18", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.18.tgz", - "integrity": "sha512-Kw2J+KzYm9C9Z9nY6+W0tEnoZOofstVCMTshli9jhQbQCy64rueGfKzPfuFBnVUqZD9JobxTh2DzHmPkp/Va/Q==", + "version": "4.2.19", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.19.tgz", + "integrity": "sha512-3a4+4mhf6VycEJyHIQLypRbiwG6aJvbQAeRAVXydMmfweEPnLLabRbdyo/Pjw8Rew9vjsh5WCdhmDaHkQnhhhA==", "license": "Apache-2.0", "dependencies": { - "@smithy/config-resolver": "^4.4.4", - "@smithy/credential-provider-imds": "^4.2.6", - "@smithy/node-config-provider": "^4.3.6", - "@smithy/property-provider": "^4.2.6", - "@smithy/smithy-client": "^4.10.1", - "@smithy/types": "^4.10.0", + "@smithy/config-resolver": "^4.4.5", + "@smithy/credential-provider-imds": "^4.2.7", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/property-provider": "^4.2.7", + "@smithy/smithy-client": "^4.10.2", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -2896,13 +4061,13 @@ } }, "node_modules/@smithy/util-endpoints": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.2.6.tgz", - "integrity": "sha512-v60VNM2+mPvgHCBXEfMCYrQ0RepP6u6xvbAkMenfe4Mi872CqNkJzgcnQL837e8NdeDxBgrWQRTluKq5Lqdhfg==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.2.7.tgz", + "integrity": "sha512-s4ILhyAvVqhMDYREeTS68R43B1V5aenV5q/V1QpRQJkCXib5BPRo4s7uNdzGtIKxaPHCfU/8YkvPAEvTpxgspg==", "license": "Apache-2.0", "dependencies": { - "@smithy/node-config-provider": "^4.3.6", - "@smithy/types": "^4.10.0", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -2922,12 +4087,12 @@ } }, "node_modules/@smithy/util-middleware": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.6.tgz", - "integrity": "sha512-qrvXUkxBSAFomM3/OEMuDVwjh4wtqK8D2uDZPShzIqOylPst6gor2Cdp6+XrH4dyksAWq/bE2aSDYBTTnj0Rxg==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.7.tgz", + "integrity": "sha512-i1IkpbOae6NvIKsEeLLM9/2q4X+M90KV3oCFgWQI4q0Qz+yUZvsr+gZPdAEAtFhWQhAHpTsJO8DRJPuwVyln+w==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.10.0", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -2935,13 +4100,13 @@ } }, "node_modules/@smithy/util-retry": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.6.tgz", - "integrity": "sha512-x7CeDQLPQ9cb6xN7fRJEjlP9NyGW/YeXWc4j/RUhg4I+H60F0PEeRc2c/z3rm9zmsdiMFzpV/rT+4UHW6KM1SA==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.7.tgz", + "integrity": "sha512-SvDdsQyF5CIASa4EYVT02LukPHVzAgUA4kMAuZ97QJc2BpAqZfA4PINB8/KOoCXEw9tsuv/jQjMeaHFvxdLNGg==", "license": "Apache-2.0", "dependencies": { - "@smithy/service-error-classification": "^4.2.6", - "@smithy/types": "^4.10.0", + "@smithy/service-error-classification": "^4.2.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -2949,14 +4114,14 @@ } }, "node_modules/@smithy/util-stream": { - "version": "4.5.7", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.7.tgz", - "integrity": "sha512-Uuy4S5Aj4oF6k1z+i2OtIBJUns4mlg29Ph4S+CqjR+f4XXpSFVgTCYLzMszHJTicYDBxKFtwq2/QSEDSS5l02A==", + "version": "4.5.8", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.8.tgz", + "integrity": "sha512-ZnnBhTapjM0YPGUSmOs0Mcg/Gg87k503qG4zU2v/+Js2Gu+daKOJMeqcQns8ajepY8tgzzfYxl6kQyZKml6O2w==", "license": "Apache-2.0", "dependencies": { - "@smithy/fetch-http-handler": "^5.3.7", - "@smithy/node-http-handler": "^4.4.6", - "@smithy/types": "^4.10.0", + "@smithy/fetch-http-handler": "^5.3.8", + "@smithy/node-http-handler": "^4.4.7", + "@smithy/types": "^4.11.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", @@ -2993,13 +4158,13 @@ } }, "node_modules/@smithy/util-waiter": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.6.tgz", - "integrity": "sha512-xU9HwUSik9UUCJmm530yvBy0AwlQFICveKmqvaaTukKkXEAhyiBdHtSrhPrH3rH+uz0ykyaE3LdgsX86C6mDCQ==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.7.tgz", + "integrity": "sha512-vHJFXi9b7kUEpHWUCY3Twl+9NPOZvQ0SAi+Ewtn48mbiJk4JY9MZmKQjGB4SCvVb9WPiSphZJYY6RIbs+grrzw==", "license": "Apache-2.0", "dependencies": { - "@smithy/abort-controller": "^4.2.6", - "@smithy/types": "^4.10.0", + "@smithy/abort-controller": "^4.2.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { diff --git a/package.json b/package.json index c721579..037eb2c 100644 --- a/package.json +++ b/package.json @@ -54,11 +54,11 @@ "typescript-eslint": "8.50.0" }, "dependencies": { - "@aws-sdk/client-dynamodb": "3.953.0", - "@aws-sdk/client-lambda": "3.953.0", - "@aws-sdk/client-sns": "3.953.0", - "@aws-sdk/lib-dynamodb": "3.953.0", - "@leanstacks/lambda-utils": "0.2.0-alpha.3", + "@aws-sdk/client-dynamodb": "3.956.0", + "@aws-sdk/client-lambda": "3.956.0", + "@aws-sdk/client-sns": "3.956.0", + "@aws-sdk/lib-dynamodb": "3.956.0", + "@leanstacks/lambda-utils": "0.3.0-alpha.4", "zod": "4.2.1" } } diff --git a/src/utils/config.test.ts b/src/utils/config.test.ts index a1dda74..f041c71 100644 --- a/src/utils/config.test.ts +++ b/src/utils/config.test.ts @@ -1,22 +1,10 @@ describe('config', () => { - let config: typeof import('./config').config; - let refreshConfig: typeof import('./config').refreshConfig; const originalEnv = process.env; beforeEach(() => { // Reset modules to clear the config cache jest.resetModules(); - // Mock logger to avoid circular dependency issues during testing - jest.doMock('./logger', () => ({ - logger: { - debug: jest.fn(), - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - }, - })); - // Reset environment variables to a clean slate process.env = { ...originalEnv }; }); @@ -33,7 +21,7 @@ describe('config', () => { process.env.TASKS_TABLE = 'my-tasks-table'; // Act - config = require('./config').config; + const { config } = require('./config'); // Assert expect(config).toBeDefined(); @@ -45,7 +33,7 @@ describe('config', () => { process.env.TASKS_TABLE = 'my-tasks-table'; // Act - config = require('./config').config; + const { config } = require('./config'); // Assert expect(config.AWS_REGION).toBe('us-east-1'); @@ -65,7 +53,7 @@ describe('config', () => { process.env.CORS_ALLOW_ORIGIN = 'https://example.com'; // Act - config = require('./config').config; + const { config } = require('./config'); // Assert expect(config.AWS_REGION).toBe('us-west-2'); @@ -83,11 +71,7 @@ describe('config', () => { expect(() => { const { config: testConfig } = require('./config'); return testConfig; - }).toThrow('Configuration validation failed'); - expect(() => { - const { config: testConfig } = require('./config'); - return testConfig; - }).toThrow('TASKS_TABLE'); + }).toThrow(); }); it('should throw error when TASKS_TABLE is empty string', () => { @@ -98,11 +82,7 @@ describe('config', () => { expect(() => { const { config: testConfig } = require('./config'); return testConfig; - }).toThrow('Configuration validation failed'); - expect(() => { - const { config: testConfig } = require('./config'); - return testConfig; - }).toThrow('TASKS_TABLE'); + }).toThrow(); }); it('should transform LOGGING_ENABLED string to boolean true', () => { @@ -111,7 +91,7 @@ describe('config', () => { process.env.LOGGING_ENABLED = 'true'; // Act - config = require('./config').config; + const { config } = require('./config'); // Assert expect(config.LOGGING_ENABLED).toBe(true); @@ -124,7 +104,7 @@ describe('config', () => { process.env.LOGGING_ENABLED = 'false'; // Act - config = require('./config').config; + const { config } = require('./config'); // Assert expect(config.LOGGING_ENABLED).toBe(false); @@ -139,8 +119,9 @@ describe('config', () => { const validLogLevels = ['debug', 'info', 'warn', 'error']; validLogLevels.forEach((level) => { jest.resetModules(); + process.env.TASKS_TABLE = 'my-tasks-table'; process.env.LOGGING_LEVEL = level; - config = require('./config').config; + const { config } = require('./config'); expect(config.LOGGING_LEVEL).toBe(level); }); }); @@ -154,7 +135,7 @@ describe('config', () => { expect(() => { const { config: testConfig } = require('./config'); return testConfig; - }).toThrow('Configuration validation failed'); + }).toThrow(); }); it('should throw error for invalid LOGGING_ENABLED value', () => { @@ -166,7 +147,7 @@ describe('config', () => { expect(() => { const { config: testConfig } = require('./config'); return testConfig; - }).toThrow('Configuration validation failed'); + }).toThrow(); }); it('should validate LOGGING_FORMAT enum values', () => { @@ -177,8 +158,9 @@ describe('config', () => { const validLogFormats = ['text', 'json']; validLogFormats.forEach((format) => { jest.resetModules(); + process.env.TASKS_TABLE = 'my-tasks-table'; process.env.LOGGING_FORMAT = format; - config = require('./config').config; + const { config } = require('./config'); expect(config.LOGGING_FORMAT).toBe(format); }); }); @@ -192,17 +174,16 @@ describe('config', () => { expect(() => { const { config: testConfig } = require('./config'); return testConfig; - }).toThrow('Configuration validation failed'); + }).toThrow(); }); }); - describe('refreshConfig', () => { + describe('refresh', () => { it('should refresh config when environment variables change', () => { // Arrange process.env.TASKS_TABLE = 'original-table'; process.env.AWS_REGION = 'us-east-1'; - refreshConfig = require('./config').refreshConfig; - config = require('./config').config; + const { config, refresh } = require('./config'); expect(config.TASKS_TABLE).toBe('original-table'); expect(config.AWS_REGION).toBe('us-east-1'); @@ -210,45 +191,36 @@ describe('config', () => { // Act - change environment and refresh process.env.TASKS_TABLE = 'updated-table'; process.env.AWS_REGION = 'eu-west-1'; - const refreshedConfig = refreshConfig(); + const refreshedConfig = refresh(); // Assert expect(refreshedConfig.TASKS_TABLE).toBe('updated-table'); expect(refreshedConfig.AWS_REGION).toBe('eu-west-1'); }); - it('should update cached config after refresh', () => { + it('should return updated config on refresh', () => { // Arrange process.env.TASKS_TABLE = 'original-table'; - refreshConfig = require('./config').refreshConfig; - const configModule = require('./config'); - const originalConfig = configModule.config; - - expect(originalConfig.TASKS_TABLE).toBe('original-table'); + const { refresh } = require('./config'); // Act process.env.TASKS_TABLE = 'new-table'; - const refreshedConfig = refreshConfig(); + const refreshedConfig = refresh(); - // Assert - refreshedConfig should have new value + // Assert expect(refreshedConfig.TASKS_TABLE).toBe('new-table'); - // The originally exported config constant won't change, but refreshConfig returns the new value - expect(originalConfig.TASKS_TABLE).toBe('original-table'); }); it('should throw error on refresh if validation fails', () => { // Arrange process.env.TASKS_TABLE = 'valid-table'; - refreshConfig = require('./config').refreshConfig; - config = require('./config').config; - - expect(config.TASKS_TABLE).toBe('valid-table'); + const { refresh } = require('./config'); // Act - remove required variable and refresh delete process.env.TASKS_TABLE; // Assert - expect(() => refreshConfig()).toThrow('Configuration validation failed'); + expect(() => refresh()).toThrow(); }); }); @@ -295,7 +267,7 @@ describe('config', () => { expect(() => { const { config: testConfig } = require('./config'); return testConfig; - }).toThrow('Configuration validation failed'); + }).toThrow(); }); it('should include field paths in error messages', () => { @@ -310,8 +282,6 @@ describe('config', () => { fail('Should have thrown an error'); } catch (error) { expect(error).toBeInstanceOf(Error); - expect((error as Error).message).toContain('TASKS_TABLE'); - expect((error as Error).message).toContain('Configuration validation failed'); } }); }); @@ -326,7 +296,7 @@ describe('config', () => { process.env.CORS_ALLOW_ORIGIN = 'https://example.com'; // Act - config = require('./config').config; + const { config } = require('./config'); // Assert - verify all expected properties exist and have correct types expect(typeof config.TASKS_TABLE).toBe('string'); diff --git a/src/utils/config.ts b/src/utils/config.ts index f7bfb39..6124b60 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -1,4 +1,5 @@ import { z } from 'zod'; +import { createConfigManager } from '@leanstacks/lambda-utils'; /** * Schema for validating environment variables @@ -29,41 +30,20 @@ const envSchema = z.object({ */ export type Config = z.infer; -// Cache for the validated config -let configCache: Config | null = null; - /** - * Validates environment variables against schema and returns a validated config object - * @throws {Error} if validation fails + * The configuration manager responsible for validating and providing access to a singleton + * instance of the application's configuration */ -const _validateConfig = (): Config => { - try { - // Parse and validate environment variables - return envSchema.parse(process.env); - } catch (error) { - // Handle Zod validation errors - if (error instanceof z.ZodError) { - const errorMessage = error.issues.map((issue) => `${issue.path.join('.')}: ${issue.message}`).join('\n'); - - throw new Error(`Configuration validation failed:\n${errorMessage}`); - } - - // Re-throw other errors - throw error; - } -}; +const configManager = createConfigManager(envSchema); /** - * Refreshes the configuration by re-validating environment variables - * Useful in tests when environment variables are changed + * Validated configuration object + * Access environment variables through this object instead of process.env directly */ -export const refreshConfig = (): Config => { - configCache = _validateConfig(); - return configCache; -}; +export const config = configManager.get(); /** - * Validated configuration object - * Access environment variables through this object instead of process.env directly + * Refreshes the configuration by re-validating environment variables + * Useful in tests when environment variables are changed */ -export const config = configCache || refreshConfig(); +export const refresh = configManager.refresh; From a1ad320653b2b7ff8f4f449917d503b6c01854eb Mon Sep 17 00:00:00 2001 From: Matthew Warman Date: Sat, 20 Dec 2025 06:25:53 -0500 Subject: [PATCH 4/9] chore: update aws-cdk-lib dependency to version 2.233.0 in package.json and package-lock.json --- infrastructure/package-lock.json | 8 ++++---- infrastructure/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/infrastructure/package-lock.json b/infrastructure/package-lock.json index 0bceb28..f2d11ff 100644 --- a/infrastructure/package-lock.json +++ b/infrastructure/package-lock.json @@ -8,7 +8,7 @@ "name": "lambda-starter-infrastructure", "version": "0.2.0", "dependencies": { - "aws-cdk-lib": "2.232.2", + "aws-cdk-lib": "2.233.0", "constructs": "10.4.4", "dotenv": "17.2.3", "source-map-support": "0.5.21", @@ -2147,9 +2147,9 @@ } }, "node_modules/aws-cdk-lib": { - "version": "2.232.2", - "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.232.2.tgz", - "integrity": "sha512-jrAxZy5mvSM9YVuF1M++hP8IIGyNmPzW8+C5nnvOnx+eYuySRiCSAzKVKlvB+UNpA0VEVCDNyTxKiu0mFBeg/g==", + "version": "2.233.0", + "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.233.0.tgz", + "integrity": "sha512-rBOzIA8TGC5eB8TyVIvckAVlX7a0/gVPE634FguhSee9RFaovjgc5+IixGyyLJhu3lLsMSjqDoqTJg2ab+p8ng==", "bundleDependencies": [ "@balena/dockerignore", "case", diff --git a/infrastructure/package.json b/infrastructure/package.json index 9124ea8..17d0da0 100644 --- a/infrastructure/package.json +++ b/infrastructure/package.json @@ -31,7 +31,7 @@ "typescript": "5.9.3" }, "dependencies": { - "aws-cdk-lib": "2.232.2", + "aws-cdk-lib": "2.233.0", "constructs": "10.4.4", "dotenv": "17.2.3", "source-map-support": "0.5.21", From 480f0f4c57c74f89192026d4a156055ffef3340c Mon Sep 17 00:00:00 2001 From: Matthew Warman Date: Wed, 24 Dec 2025 05:52:44 -0500 Subject: [PATCH 5/9] chore: update dependencies to latest versions - Bump @typescript-eslint/eslint-plugin and @typescript-eslint/parser from 8.50.0 to 8.50.1 - Update AWS SDK clients from 3.956.0 to 3.958.0 - Upgrade @leanstacks/lambda-utils from 0.3.0-alpha.4 to 0.4.0-alpha.1 --- package-lock.json | 2070 ++++++++++++++++++--------------------------- package.json | 16 +- 2 files changed, 822 insertions(+), 1264 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6eced19..043c6ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,19 +9,19 @@ "version": "0.2.0", "license": "MIT", "dependencies": { - "@aws-sdk/client-dynamodb": "3.956.0", - "@aws-sdk/client-lambda": "3.956.0", - "@aws-sdk/client-sns": "3.956.0", - "@aws-sdk/lib-dynamodb": "3.956.0", - "@leanstacks/lambda-utils": "0.3.0-alpha.4", + "@aws-sdk/client-dynamodb": "3.958.0", + "@aws-sdk/client-lambda": "3.958.0", + "@aws-sdk/client-sns": "3.958.0", + "@aws-sdk/lib-dynamodb": "3.958.0", + "@leanstacks/lambda-utils": "0.4.0-alpha.1", "zod": "4.2.1" }, "devDependencies": { "@types/aws-lambda": "8.10.159", "@types/jest": "30.0.0", "@types/node": "25.0.3", - "@typescript-eslint/eslint-plugin": "8.50.0", - "@typescript-eslint/parser": "8.50.0", + "@typescript-eslint/eslint-plugin": "8.50.1", + "@typescript-eslint/parser": "8.50.1", "eslint": "9.39.2", "eslint-config-prettier": "10.1.8", "globals": "16.5.0", @@ -32,7 +32,7 @@ "ts-jest": "29.4.6", "ts-node": "10.9.2", "typescript": "5.9.3", - "typescript-eslint": "8.50.0" + "typescript-eslint": "8.50.1" } }, "node_modules/@aws-crypto/crc32": { @@ -175,27 +175,27 @@ } }, "node_modules/@aws-sdk/client-dynamodb": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.956.0.tgz", - "integrity": "sha512-mM99L5f8Kg5IhdiZbp+WzJ1IYoxHQ/t9eEe29oh9xp7L7VafOQytJyKMVNOIsoiIRJT6XYtst5493G4JhcU4CQ==", + "version": "3.958.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.958.0.tgz", + "integrity": "sha512-R3G5cxf3fsL0CEcTbY1VkSwU1FJtImrhA5I9Eepd8nEO6isZ6C99qVKZtDG9eG7qVNK6zTzUigXac/GFrn6hYA==", "license": "Apache-2.0", "peer": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.956.0", - "@aws-sdk/credential-provider-node": "3.956.0", - "@aws-sdk/dynamodb-codec": "3.956.0", - "@aws-sdk/middleware-endpoint-discovery": "3.956.0", - "@aws-sdk/middleware-host-header": "3.956.0", - "@aws-sdk/middleware-logger": "3.956.0", - "@aws-sdk/middleware-recursion-detection": "3.956.0", - "@aws-sdk/middleware-user-agent": "3.956.0", - "@aws-sdk/region-config-resolver": "3.956.0", - "@aws-sdk/types": "3.956.0", - "@aws-sdk/util-endpoints": "3.956.0", - "@aws-sdk/util-user-agent-browser": "3.956.0", - "@aws-sdk/util-user-agent-node": "3.956.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/credential-provider-node": "3.958.0", + "@aws-sdk/dynamodb-codec": "3.957.0", + "@aws-sdk/middleware-endpoint-discovery": "3.957.0", + "@aws-sdk/middleware-host-header": "3.957.0", + "@aws-sdk/middleware-logger": "3.957.0", + "@aws-sdk/middleware-recursion-detection": "3.957.0", + "@aws-sdk/middleware-user-agent": "3.957.0", + "@aws-sdk/region-config-resolver": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@aws-sdk/util-endpoints": "3.957.0", + "@aws-sdk/util-user-agent-browser": "3.957.0", + "@aws-sdk/util-user-agent-node": "3.957.0", "@smithy/config-resolver": "^4.4.5", "@smithy/core": "^3.20.0", "@smithy/fetch-http-handler": "^5.3.8", @@ -228,144 +228,25 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/middleware-endpoint-discovery": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.956.0.tgz", - "integrity": "sha512-p8oOhksZg3qxluKBM6J5F9Tv4cqzkjYYQO3iU3BENT3NXGvoHuaBbj6G/hXsKl1/jfGNUyIOpO+59r1L4zNqOg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/endpoint-cache": "3.953.0", - "@aws-sdk/types": "3.956.0", - "@smithy/node-config-provider": "^4.3.7", - "@smithy/protocol-http": "^5.3.7", - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/middleware-host-header": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.956.0.tgz", - "integrity": "sha512-JujNJDp/dj1DbsI0ntzhrz2uJ4jpumcKtr743eMpEhdboYjuu/UzY8/7n1h5JbgU9TNXgqE9lgQNa5QPG0Tvsg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.956.0", - "@smithy/protocol-http": "^5.3.7", - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/middleware-logger": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.956.0.tgz", - "integrity": "sha512-Qff39yEOPYgRsm4SrkHOvS0nSoxXILYnC8Akp0uMRi2lOcZVyXL3WCWqIOtI830qVI4GPa796sleKguxx50RHg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.956.0", - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.956.0.tgz", - "integrity": "sha512-/f4JxL2kSCYhy63wovqts6SJkpalSLvuFe78ozt3ClrGoHGyr69o7tPRYx5U7azLgvrIGjsWUyTayeAk3YHIVQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.956.0", - "@aws/lambda-invoke-store": "^0.2.2", - "@smithy/protocol-http": "^5.3.7", - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/region-config-resolver": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.956.0.tgz", - "integrity": "sha512-byU5XYekW7+rZ3e067y038wlrpnPkdI4fMxcHCHrv+TAfzl8CCk5xLyzerQtXZR8cVPVOXuaYWe1zKW0uCnXUA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.956.0", - "@smithy/config-resolver": "^4.4.5", - "@smithy/node-config-provider": "^4.3.7", - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/types": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", - "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/util-endpoints": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.956.0.tgz", - "integrity": "sha512-xZ5CBoubS4rs9JkFniKNShDtfqxaMUnwaebYMoybZm070q9+omFkQkJYXl7kopTViEgZgQl1sAsAkrawBM8qEQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.956.0", - "@smithy/types": "^4.11.0", - "@smithy/url-parser": "^4.2.7", - "@smithy/util-endpoints": "^3.2.7", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-dynamodb/node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.956.0.tgz", - "integrity": "sha512-s8KwYR3HqiGNni7a1DN2P3RUog64QoBQ6VCSzJkHBWb6++8KSOpqeeDkfmEz+22y1LOne+bRrpDGKa0aqOc3rQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.956.0", - "@smithy/types": "^4.11.0", - "bowser": "^2.11.0", - "tslib": "^2.6.2" - } - }, "node_modules/@aws-sdk/client-lambda": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.956.0.tgz", - "integrity": "sha512-BiS7Z/rZA/1dquEzBJ/tNNpRuivOEv2bx4PVDbjiLXyaww/Rds+zkhP+0KdYPYWztKXT96CGRH7DCEiN9N4EEQ==", + "version": "3.958.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.958.0.tgz", + "integrity": "sha512-gwEqpDkgPLbFfewQkRRgnqn9iCfnd5BUVFUZpUoyq8DxzPmNn/lEVMkBaNCqwIXx07jd46+qd1neWBrH2UYi2Q==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.956.0", - "@aws-sdk/credential-provider-node": "3.956.0", - "@aws-sdk/middleware-host-header": "3.956.0", - "@aws-sdk/middleware-logger": "3.956.0", - "@aws-sdk/middleware-recursion-detection": "3.956.0", - "@aws-sdk/middleware-user-agent": "3.956.0", - "@aws-sdk/region-config-resolver": "3.956.0", - "@aws-sdk/types": "3.956.0", - "@aws-sdk/util-endpoints": "3.956.0", - "@aws-sdk/util-user-agent-browser": "3.956.0", - "@aws-sdk/util-user-agent-node": "3.956.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/credential-provider-node": "3.958.0", + "@aws-sdk/middleware-host-header": "3.957.0", + "@aws-sdk/middleware-logger": "3.957.0", + "@aws-sdk/middleware-recursion-detection": "3.957.0", + "@aws-sdk/middleware-user-agent": "3.957.0", + "@aws-sdk/region-config-resolver": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@aws-sdk/util-endpoints": "3.957.0", + "@aws-sdk/util-user-agent-browser": "3.957.0", + "@aws-sdk/util-user-agent-node": "3.957.0", "@smithy/config-resolver": "^4.4.5", "@smithy/core": "^3.20.0", "@smithy/eventstream-serde-browser": "^4.2.7", @@ -402,132 +283,82 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/middleware-host-header": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.956.0.tgz", - "integrity": "sha512-JujNJDp/dj1DbsI0ntzhrz2uJ4jpumcKtr743eMpEhdboYjuu/UzY8/7n1h5JbgU9TNXgqE9lgQNa5QPG0Tvsg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.956.0", - "@smithy/protocol-http": "^5.3.7", - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/middleware-logger": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.956.0.tgz", - "integrity": "sha512-Qff39yEOPYgRsm4SrkHOvS0nSoxXILYnC8Akp0uMRi2lOcZVyXL3WCWqIOtI830qVI4GPa796sleKguxx50RHg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.956.0", - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.956.0.tgz", - "integrity": "sha512-/f4JxL2kSCYhy63wovqts6SJkpalSLvuFe78ozt3ClrGoHGyr69o7tPRYx5U7azLgvrIGjsWUyTayeAk3YHIVQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.956.0", - "@aws/lambda-invoke-store": "^0.2.2", - "@smithy/protocol-http": "^5.3.7", - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/region-config-resolver": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.956.0.tgz", - "integrity": "sha512-byU5XYekW7+rZ3e067y038wlrpnPkdI4fMxcHCHrv+TAfzl8CCk5xLyzerQtXZR8cVPVOXuaYWe1zKW0uCnXUA==", + "node_modules/@aws-sdk/client-sns": { + "version": "3.958.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sns/-/client-sns-3.958.0.tgz", + "integrity": "sha512-KSsfhNXt8npsadJL5tF3UhARkPtqcbszMt3bKwkF4j5KA5Hdf5XD6tzjwBGkJnvBPHZJbLZEquzIvt4Z3KGIrw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.956.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/credential-provider-node": "3.958.0", + "@aws-sdk/middleware-host-header": "3.957.0", + "@aws-sdk/middleware-logger": "3.957.0", + "@aws-sdk/middleware-recursion-detection": "3.957.0", + "@aws-sdk/middleware-user-agent": "3.957.0", + "@aws-sdk/region-config-resolver": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@aws-sdk/util-endpoints": "3.957.0", + "@aws-sdk/util-user-agent-browser": "3.957.0", + "@aws-sdk/util-user-agent-node": "3.957.0", "@smithy/config-resolver": "^4.4.5", + "@smithy/core": "^3.20.0", + "@smithy/fetch-http-handler": "^5.3.8", + "@smithy/hash-node": "^4.2.7", + "@smithy/invalid-dependency": "^4.2.7", + "@smithy/middleware-content-length": "^4.2.7", + "@smithy/middleware-endpoint": "^4.4.1", + "@smithy/middleware-retry": "^4.4.17", + "@smithy/middleware-serde": "^4.2.8", + "@smithy/middleware-stack": "^4.2.7", "@smithy/node-config-provider": "^4.3.7", - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/types": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", - "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/util-endpoints": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.956.0.tgz", - "integrity": "sha512-xZ5CBoubS4rs9JkFniKNShDtfqxaMUnwaebYMoybZm070q9+omFkQkJYXl7kopTViEgZgQl1sAsAkrawBM8qEQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.956.0", + "@smithy/node-http-handler": "^4.4.7", + "@smithy/protocol-http": "^5.3.7", + "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.16", + "@smithy/util-defaults-mode-node": "^4.2.19", "@smithy/util-endpoints": "^3.2.7", + "@smithy/util-middleware": "^4.2.7", + "@smithy/util-retry": "^4.2.7", + "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-lambda/node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.956.0.tgz", - "integrity": "sha512-s8KwYR3HqiGNni7a1DN2P3RUog64QoBQ6VCSzJkHBWb6++8KSOpqeeDkfmEz+22y1LOne+bRrpDGKa0aqOc3rQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.956.0", - "@smithy/types": "^4.11.0", - "bowser": "^2.11.0", - "tslib": "^2.6.2" - } - }, - "node_modules/@aws-sdk/client-sns": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sns/-/client-sns-3.956.0.tgz", - "integrity": "sha512-xd9bPtTaLid0y68HGK8m/C9Ig6tUrGsqmKzXOLj/LXKdK38XVeJcGB765F2JGMZ+JhjrTpz/w3QykMGiWMgoVA==", + "node_modules/@aws-sdk/client-sqs": { + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sqs/-/client-sqs-3.957.0.tgz", + "integrity": "sha512-V5hoymq0nnS7eAoMedj5p4YSyAbxkS4bzC8xl1tKEOmKIXDA0+uO1Ink5QIgUVbB7DEsLbdrgHE9G77DqwvcQA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.956.0", - "@aws-sdk/credential-provider-node": "3.956.0", - "@aws-sdk/middleware-host-header": "3.956.0", - "@aws-sdk/middleware-logger": "3.956.0", - "@aws-sdk/middleware-recursion-detection": "3.956.0", - "@aws-sdk/middleware-user-agent": "3.956.0", - "@aws-sdk/region-config-resolver": "3.956.0", - "@aws-sdk/types": "3.956.0", - "@aws-sdk/util-endpoints": "3.956.0", - "@aws-sdk/util-user-agent-browser": "3.956.0", - "@aws-sdk/util-user-agent-node": "3.956.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/credential-provider-node": "3.957.0", + "@aws-sdk/middleware-host-header": "3.957.0", + "@aws-sdk/middleware-logger": "3.957.0", + "@aws-sdk/middleware-recursion-detection": "3.957.0", + "@aws-sdk/middleware-sdk-sqs": "3.957.0", + "@aws-sdk/middleware-user-agent": "3.957.0", + "@aws-sdk/region-config-resolver": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@aws-sdk/util-endpoints": "3.957.0", + "@aws-sdk/util-user-agent-browser": "3.957.0", + "@aws-sdk/util-user-agent-node": "3.957.0", "@smithy/config-resolver": "^4.4.5", "@smithy/core": "^3.20.0", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/hash-node": "^4.2.7", "@smithy/invalid-dependency": "^4.2.7", + "@smithy/md5-js": "^4.2.7", "@smithy/middleware-content-length": "^4.2.7", "@smithy/middleware-endpoint": "^4.4.1", "@smithy/middleware-retry": "^4.4.17", @@ -554,28 +385,73 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-sns/node_modules/@aws-sdk/middleware-host-header": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.956.0.tgz", - "integrity": "sha512-JujNJDp/dj1DbsI0ntzhrz2uJ4jpumcKtr743eMpEhdboYjuu/UzY8/7n1h5JbgU9TNXgqE9lgQNa5QPG0Tvsg==", + "node_modules/@aws-sdk/client-sqs/node_modules/@aws-sdk/client-sso": { + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.957.0.tgz", + "integrity": "sha512-iRdRjd+IpOogqRPt8iNRcg30J53z4rRfMviGwpKgsEa/fx3inCUPOuca3Ap7ZDES0atnEg3KGSJ3V/NQiEJ4BA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.956.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/middleware-host-header": "3.957.0", + "@aws-sdk/middleware-logger": "3.957.0", + "@aws-sdk/middleware-recursion-detection": "3.957.0", + "@aws-sdk/middleware-user-agent": "3.957.0", + "@aws-sdk/region-config-resolver": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@aws-sdk/util-endpoints": "3.957.0", + "@aws-sdk/util-user-agent-browser": "3.957.0", + "@aws-sdk/util-user-agent-node": "3.957.0", + "@smithy/config-resolver": "^4.4.5", + "@smithy/core": "^3.20.0", + "@smithy/fetch-http-handler": "^5.3.8", + "@smithy/hash-node": "^4.2.7", + "@smithy/invalid-dependency": "^4.2.7", + "@smithy/middleware-content-length": "^4.2.7", + "@smithy/middleware-endpoint": "^4.4.1", + "@smithy/middleware-retry": "^4.4.17", + "@smithy/middleware-serde": "^4.2.8", + "@smithy/middleware-stack": "^4.2.7", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/node-http-handler": "^4.4.7", "@smithy/protocol-http": "^5.3.7", + "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", + "@smithy/url-parser": "^4.2.7", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.16", + "@smithy/util-defaults-mode-node": "^4.2.19", + "@smithy/util-endpoints": "^3.2.7", + "@smithy/util-middleware": "^4.2.7", + "@smithy/util-retry": "^4.2.7", + "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-sns/node_modules/@aws-sdk/middleware-logger": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.956.0.tgz", - "integrity": "sha512-Qff39yEOPYgRsm4SrkHOvS0nSoxXILYnC8Akp0uMRi2lOcZVyXL3WCWqIOtI830qVI4GPa796sleKguxx50RHg==", + "node_modules/@aws-sdk/client-sqs/node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.957.0.tgz", + "integrity": "sha512-YuoZmIeE91YIeUfihh8SiSu546KtTvU+4rG5SaL30U9+nGq6P11GRRgqF0ANUyRseLC9ONHt+utar4gbO3++og==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.956.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/credential-provider-env": "3.957.0", + "@aws-sdk/credential-provider-http": "3.957.0", + "@aws-sdk/credential-provider-login": "3.957.0", + "@aws-sdk/credential-provider-process": "3.957.0", + "@aws-sdk/credential-provider-sso": "3.957.0", + "@aws-sdk/credential-provider-web-identity": "3.957.0", + "@aws-sdk/nested-clients": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@smithy/credential-provider-imds": "^4.2.7", + "@smithy/property-provider": "^4.2.7", + "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, @@ -583,15 +459,18 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-sns/node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.956.0.tgz", - "integrity": "sha512-/f4JxL2kSCYhy63wovqts6SJkpalSLvuFe78ozt3ClrGoHGyr69o7tPRYx5U7azLgvrIGjsWUyTayeAk3YHIVQ==", + "node_modules/@aws-sdk/client-sqs/node_modules/@aws-sdk/credential-provider-login": { + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.957.0.tgz", + "integrity": "sha512-XcD5NEQDWYk8B4gs89bkwf2d+DNF8oS2NR5RoHJEbX4l8KErVATUjpEYVn6/rAFEktungxlYTnQ5wh0cIQvP5w==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.956.0", - "@aws/lambda-invoke-store": "^0.2.2", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/nested-clients": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@smithy/property-provider": "^4.2.7", "@smithy/protocol-http": "^5.3.7", + "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, @@ -599,15 +478,22 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-sns/node_modules/@aws-sdk/region-config-resolver": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.956.0.tgz", - "integrity": "sha512-byU5XYekW7+rZ3e067y038wlrpnPkdI4fMxcHCHrv+TAfzl8CCk5xLyzerQtXZR8cVPVOXuaYWe1zKW0uCnXUA==", + "node_modules/@aws-sdk/client-sqs/node_modules/@aws-sdk/credential-provider-node": { + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.957.0.tgz", + "integrity": "sha512-b9FT/7BQcJ001w+3JbTiJXfxHrWvPb7zDvvC1i1FKcNOvyCt3BGu04n4nO/b71a3iBnbfBXI89hCIZQsuLcEgw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.956.0", - "@smithy/config-resolver": "^4.4.5", - "@smithy/node-config-provider": "^4.3.7", + "@aws-sdk/credential-provider-env": "3.957.0", + "@aws-sdk/credential-provider-http": "3.957.0", + "@aws-sdk/credential-provider-ini": "3.957.0", + "@aws-sdk/credential-provider-process": "3.957.0", + "@aws-sdk/credential-provider-sso": "3.957.0", + "@aws-sdk/credential-provider-web-identity": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@smithy/credential-provider-imds": "^4.2.7", + "@smithy/property-provider": "^4.2.7", + "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, @@ -615,12 +501,18 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-sns/node_modules/@aws-sdk/types": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", - "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", + "node_modules/@aws-sdk/client-sqs/node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.957.0.tgz", + "integrity": "sha512-gTLPJFOkGtn3tVGglRhCar2oOobK1YctZRAT8nfJr17uaSRoAP46zIIHNYBZZUMqImb0qAHD9Ugm+Zd9sIqxyA==", "license": "Apache-2.0", "dependencies": { + "@aws-sdk/client-sso": "3.957.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/token-providers": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@smithy/property-provider": "^4.2.7", + "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, @@ -628,52 +520,42 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-sns/node_modules/@aws-sdk/util-endpoints": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.956.0.tgz", - "integrity": "sha512-xZ5CBoubS4rs9JkFniKNShDtfqxaMUnwaebYMoybZm070q9+omFkQkJYXl7kopTViEgZgQl1sAsAkrawBM8qEQ==", + "node_modules/@aws-sdk/client-sqs/node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.957.0.tgz", + "integrity": "sha512-x17xMeD7c+rKEsWachGIMifACqkugskrETWz18QDWismFcrmUuOcZu5rUa8s9y1pnITLKUQ1xU/qDLPH52jLlA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.956.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/nested-clients": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@smithy/property-provider": "^4.2.7", + "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", - "@smithy/url-parser": "^4.2.7", - "@smithy/util-endpoints": "^3.2.7", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-sns/node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.956.0.tgz", - "integrity": "sha512-s8KwYR3HqiGNni7a1DN2P3RUog64QoBQ6VCSzJkHBWb6++8KSOpqeeDkfmEz+22y1LOne+bRrpDGKa0aqOc3rQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.956.0", - "@smithy/types": "^4.11.0", - "bowser": "^2.11.0", - "tslib": "^2.6.2" - } - }, - "node_modules/@aws-sdk/client-sso": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.956.0.tgz", - "integrity": "sha512-TCxCa9B1IMILvk/7sig0fRQzff+M2zBQVZGWOJL8SAZq/gfElIMAf/nYjQwMhXjyq8PFDRGm4GN8ZhNKPeNleQ==", + "node_modules/@aws-sdk/client-sqs/node_modules/@aws-sdk/nested-clients": { + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.957.0.tgz", + "integrity": "sha512-PZUFtaUTSZWO+mbgQGWSiwz3EqedsuKNb7Xoxjzh5rfJE352DD4/jScQEhVPxvdLw62IK9b5UDu5kZlxzBs9Ow==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.956.0", - "@aws-sdk/middleware-host-header": "3.956.0", - "@aws-sdk/middleware-logger": "3.956.0", - "@aws-sdk/middleware-recursion-detection": "3.956.0", - "@aws-sdk/middleware-user-agent": "3.956.0", - "@aws-sdk/region-config-resolver": "3.956.0", - "@aws-sdk/types": "3.956.0", - "@aws-sdk/util-endpoints": "3.956.0", - "@aws-sdk/util-user-agent-browser": "3.956.0", - "@aws-sdk/util-user-agent-node": "3.956.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/middleware-host-header": "3.957.0", + "@aws-sdk/middleware-logger": "3.957.0", + "@aws-sdk/middleware-recursion-detection": "3.957.0", + "@aws-sdk/middleware-user-agent": "3.957.0", + "@aws-sdk/region-config-resolver": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@aws-sdk/util-endpoints": "3.957.0", + "@aws-sdk/util-user-agent-browser": "3.957.0", + "@aws-sdk/util-user-agent-node": "3.957.0", "@smithy/config-resolver": "^4.4.5", "@smithy/core": "^3.20.0", "@smithy/fetch-http-handler": "^5.3.8", @@ -705,44 +587,17 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/middleware-host-header": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.956.0.tgz", - "integrity": "sha512-JujNJDp/dj1DbsI0ntzhrz2uJ4jpumcKtr743eMpEhdboYjuu/UzY8/7n1h5JbgU9TNXgqE9lgQNa5QPG0Tvsg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.956.0", - "@smithy/protocol-http": "^5.3.7", - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/middleware-logger": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.956.0.tgz", - "integrity": "sha512-Qff39yEOPYgRsm4SrkHOvS0nSoxXILYnC8Akp0uMRi2lOcZVyXL3WCWqIOtI830qVI4GPa796sleKguxx50RHg==", + "node_modules/@aws-sdk/client-sqs/node_modules/@aws-sdk/token-providers": { + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.957.0.tgz", + "integrity": "sha512-oSwo3BZ6gcvhjTg036V0UQmtENUeNwfCU35iDckX961CdI1alQ3TKRWLzKrwvXCbrOx+bZsuA1PHsTbNhI/+Fw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.956.0", - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.956.0.tgz", - "integrity": "sha512-/f4JxL2kSCYhy63wovqts6SJkpalSLvuFe78ozt3ClrGoHGyr69o7tPRYx5U7azLgvrIGjsWUyTayeAk3YHIVQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.956.0", - "@aws/lambda-invoke-store": "^0.2.2", - "@smithy/protocol-http": "^5.3.7", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/nested-clients": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@smithy/property-provider": "^4.2.7", + "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, @@ -750,71 +605,63 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/region-config-resolver": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.956.0.tgz", - "integrity": "sha512-byU5XYekW7+rZ3e067y038wlrpnPkdI4fMxcHCHrv+TAfzl8CCk5xLyzerQtXZR8cVPVOXuaYWe1zKW0uCnXUA==", + "node_modules/@aws-sdk/client-sso": { + "version": "3.958.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.958.0.tgz", + "integrity": "sha512-6qNCIeaMzKzfqasy2nNRuYnMuaMebCcCPP4J2CVGkA8QYMbIVKPlkn9bpB20Vxe6H/r3jtCCLQaOJjVTx/6dXg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.956.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/middleware-host-header": "3.957.0", + "@aws-sdk/middleware-logger": "3.957.0", + "@aws-sdk/middleware-recursion-detection": "3.957.0", + "@aws-sdk/middleware-user-agent": "3.957.0", + "@aws-sdk/region-config-resolver": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@aws-sdk/util-endpoints": "3.957.0", + "@aws-sdk/util-user-agent-browser": "3.957.0", + "@aws-sdk/util-user-agent-node": "3.957.0", "@smithy/config-resolver": "^4.4.5", + "@smithy/core": "^3.20.0", + "@smithy/fetch-http-handler": "^5.3.8", + "@smithy/hash-node": "^4.2.7", + "@smithy/invalid-dependency": "^4.2.7", + "@smithy/middleware-content-length": "^4.2.7", + "@smithy/middleware-endpoint": "^4.4.1", + "@smithy/middleware-retry": "^4.4.17", + "@smithy/middleware-serde": "^4.2.8", + "@smithy/middleware-stack": "^4.2.7", "@smithy/node-config-provider": "^4.3.7", - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/types": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", - "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/util-endpoints": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.956.0.tgz", - "integrity": "sha512-xZ5CBoubS4rs9JkFniKNShDtfqxaMUnwaebYMoybZm070q9+omFkQkJYXl7kopTViEgZgQl1sAsAkrawBM8qEQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.956.0", + "@smithy/node-http-handler": "^4.4.7", + "@smithy/protocol-http": "^5.3.7", + "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.16", + "@smithy/util-defaults-mode-node": "^4.2.19", "@smithy/util-endpoints": "^3.2.7", + "@smithy/util-middleware": "^4.2.7", + "@smithy/util-retry": "^4.2.7", + "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-sso/node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.956.0.tgz", - "integrity": "sha512-s8KwYR3HqiGNni7a1DN2P3RUog64QoBQ6VCSzJkHBWb6++8KSOpqeeDkfmEz+22y1LOne+bRrpDGKa0aqOc3rQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.956.0", - "@smithy/types": "^4.11.0", - "bowser": "^2.11.0", - "tslib": "^2.6.2" - } - }, "node_modules/@aws-sdk/core": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.956.0.tgz", - "integrity": "sha512-BMOCXZNz5z4cR3/SaNHUfeoZQUG/y39bLscdLUgg3RL6mDOhuINIqMc0qc6G3kpwDTLVdXikF4nmx2UrRK9y5A==", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.957.0.tgz", + "integrity": "sha512-DrZgDnF1lQZv75a52nFWs6MExihJF2GZB6ETZRqr6jMwhrk2kbJPUtvgbifwcL7AYmVqHQDJBrR/MqkwwFCpiw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.956.0", - "@aws-sdk/xml-builder": "3.956.0", + "@aws-sdk/types": "3.957.0", + "@aws-sdk/xml-builder": "3.957.0", "@smithy/core": "^3.20.0", "@smithy/node-config-provider": "^4.3.7", "@smithy/property-provider": "^4.2.7", @@ -831,41 +678,14 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/core/node_modules/@aws-sdk/types": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", - "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/core/node_modules/@aws-sdk/xml-builder": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.956.0.tgz", - "integrity": "sha512-x/IvXUeQYNUEQojpRIQpFt4X7XGxqzjUlXFRdwaTCtTz3q1droXVJvYOhnX3KiMgzeHGlBJfY4Nmq3oZNEUGFw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.11.0", - "fast-xml-parser": "5.2.5", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.956.0.tgz", - "integrity": "sha512-aLJavJMPVTvhmggJ0pcdCKEWJk3sL9QkJkUIEoTzOou7HnxWS66N4sC5e8y27AF2nlnYfIxq3hkEiZlGi/vlfA==", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.957.0.tgz", + "integrity": "sha512-475mkhGaWCr+Z52fOOVb/q2VHuNvqEDixlYIkeaO6xJ6t9qR0wpLt4hOQaR6zR1wfZV0SlE7d8RErdYq/PByog==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.956.0", - "@aws-sdk/types": "3.956.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/types": "3.957.0", "@smithy/property-provider": "^4.2.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" @@ -874,27 +694,14 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/credential-provider-env/node_modules/@aws-sdk/types": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", - "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.956.0.tgz", - "integrity": "sha512-VsKzBNhwT6XJdW3HQX6o4KOHj1MAzSwA8/zCsT9mOGecozw1yeCcQPtlWDSlfsfygKVCXz7fiJzU03yl11NKMA==", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.957.0.tgz", + "integrity": "sha512-8dS55QHRxXgJlHkEYaCGZIhieCs9NU1HU1BcqQ4RfUdSsfRdxxktqUKgCnBnOOn0oD3PPA8cQOCAVgIyRb3Rfw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.956.0", - "@aws-sdk/types": "3.956.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/types": "3.957.0", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/node-http-handler": "^4.4.7", "@smithy/property-provider": "^4.2.7", @@ -908,34 +715,21 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/credential-provider-http/node_modules/@aws-sdk/types": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", - "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.956.0.tgz", - "integrity": "sha512-TlDy+IGr0JIRBwnPdV31J1kWXEcfsR3OzcNVWQrguQdHeTw2lU5eft16kdizo6OruqcZRF/LvHBDwAWx4u51ww==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.956.0", - "@aws-sdk/credential-provider-env": "3.956.0", - "@aws-sdk/credential-provider-http": "3.956.0", - "@aws-sdk/credential-provider-login": "3.956.0", - "@aws-sdk/credential-provider-process": "3.956.0", - "@aws-sdk/credential-provider-sso": "3.956.0", - "@aws-sdk/credential-provider-web-identity": "3.956.0", - "@aws-sdk/nested-clients": "3.956.0", - "@aws-sdk/types": "3.956.0", + "version": "3.958.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.958.0.tgz", + "integrity": "sha512-u7twvZa1/6GWmPBZs6DbjlegCoNzNjBsMS/6fvh5quByYrcJr/uLd8YEr7S3UIq4kR/gSnHqcae7y2nL2bqZdg==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.957.0", + "@aws-sdk/credential-provider-env": "3.957.0", + "@aws-sdk/credential-provider-http": "3.957.0", + "@aws-sdk/credential-provider-login": "3.958.0", + "@aws-sdk/credential-provider-process": "3.957.0", + "@aws-sdk/credential-provider-sso": "3.958.0", + "@aws-sdk/credential-provider-web-identity": "3.958.0", + "@aws-sdk/nested-clients": "3.958.0", + "@aws-sdk/types": "3.957.0", "@smithy/credential-provider-imds": "^4.2.7", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", @@ -946,28 +740,15 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/credential-provider-ini/node_modules/@aws-sdk/types": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", - "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/credential-provider-login": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.956.0.tgz", - "integrity": "sha512-p2Y62mdIlUpiyi5tvn8cKTja5kq1e3Rm5gm4wpNQ9caTayfkIEXyKrbP07iepTv60Coaylq9Fx6b5En/siAeGA==", + "version": "3.958.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.958.0.tgz", + "integrity": "sha512-sDwtDnBSszUIbzbOORGh5gmXGl9aK25+BHb4gb1aVlqB+nNL2+IUEJA62+CE55lXSH8qXF90paivjK8tOHTwPA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.956.0", - "@aws-sdk/nested-clients": "3.956.0", - "@aws-sdk/types": "3.956.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/nested-clients": "3.958.0", + "@aws-sdk/types": "3.957.0", "@smithy/property-provider": "^4.2.7", "@smithy/protocol-http": "^5.3.7", "@smithy/shared-ini-file-loader": "^4.4.2", @@ -978,32 +759,19 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/credential-provider-login/node_modules/@aws-sdk/types": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", - "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.956.0.tgz", - "integrity": "sha512-ITjp7uAQh17ljUsCWkPRmLjyFfupGlJVUfTLHnZJ+c7G0P0PDRquaM+fBSh0y33tauHsBa5fGnCCLRo5hy9sGQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.956.0", - "@aws-sdk/credential-provider-http": "3.956.0", - "@aws-sdk/credential-provider-ini": "3.956.0", - "@aws-sdk/credential-provider-process": "3.956.0", - "@aws-sdk/credential-provider-sso": "3.956.0", - "@aws-sdk/credential-provider-web-identity": "3.956.0", - "@aws-sdk/types": "3.956.0", + "version": "3.958.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.958.0.tgz", + "integrity": "sha512-vdoZbNG2dt66I7EpN3fKCzi6fp9xjIiwEA/vVVgqO4wXCGw8rKPIdDUus4e13VvTr330uQs2W0UNg/7AgtquEQ==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.957.0", + "@aws-sdk/credential-provider-http": "3.957.0", + "@aws-sdk/credential-provider-ini": "3.958.0", + "@aws-sdk/credential-provider-process": "3.957.0", + "@aws-sdk/credential-provider-sso": "3.958.0", + "@aws-sdk/credential-provider-web-identity": "3.958.0", + "@aws-sdk/types": "3.957.0", "@smithy/credential-provider-imds": "^4.2.7", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", @@ -1014,27 +782,14 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/credential-provider-node/node_modules/@aws-sdk/types": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", - "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.956.0.tgz", - "integrity": "sha512-wpAex+/LGVWkHPchsn9FWy1ahFualIeSYq3ADFc262ljJjrltOWGh3+cu3OK3gTMkX6VEsl+lFvy1P7Bk7cgXA==", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.957.0.tgz", + "integrity": "sha512-/KIz9kadwbeLy6SKvT79W81Y+hb/8LMDyeloA2zhouE28hmne+hLn0wNCQXAAupFFlYOAtZR2NTBs7HBAReJlg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.956.0", - "@aws-sdk/types": "3.956.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/types": "3.957.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", @@ -1044,29 +799,16 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/credential-provider-process/node_modules/@aws-sdk/types": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", - "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.956.0.tgz", - "integrity": "sha512-IRFSDF32x8TpOEYSGMcGQVJUiYuJaFkek0aCjW0klNIZHBF1YpflVpUarK9DJe4v4ryfVq3c0bqR/JFui8QFmw==", + "version": "3.958.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.958.0.tgz", + "integrity": "sha512-CBYHJ5ufp8HC4q+o7IJejCUctJXWaksgpmoFpXerbjAso7/Fg7LLUu9inXVOxlHKLlvYekDXjIUBXDJS2WYdgg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-sso": "3.956.0", - "@aws-sdk/core": "3.956.0", - "@aws-sdk/token-providers": "3.956.0", - "@aws-sdk/types": "3.956.0", + "@aws-sdk/client-sso": "3.958.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/token-providers": "3.958.0", + "@aws-sdk/types": "3.957.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", @@ -1076,28 +818,15 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/types": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", - "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.956.0.tgz", - "integrity": "sha512-4YkmjwZC+qoUKlVOY9xNx7BTKRdJ1R1/Zjk2QSW5aWtwkk2e07ZUQvUpbW4vGpAxGm1K4EgRcowuSpOsDTh44Q==", + "version": "3.958.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.958.0.tgz", + "integrity": "sha512-dgnvwjMq5Y66WozzUzxNkCFap+umHUtqMMKlr8z/vl9NYMLem/WUbWNpFFOVFWquXikc+ewtpBMR4KEDXfZ+KA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.956.0", - "@aws-sdk/nested-clients": "3.956.0", - "@aws-sdk/types": "3.956.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/nested-clients": "3.958.0", + "@aws-sdk/types": "3.957.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", @@ -1107,26 +836,13 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/credential-provider-web-identity/node_modules/@aws-sdk/types": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", - "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/dynamodb-codec": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/dynamodb-codec/-/dynamodb-codec-3.956.0.tgz", - "integrity": "sha512-18+va/liQYkUVn5Wdz7h4rQQHq5QplFmQBAnkIOpZoN4ir36lrS9IeyoRbcrj8AxZRTHzl+vGc69Bq3sq9s5xg==", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/dynamodb-codec/-/dynamodb-codec-3.957.0.tgz", + "integrity": "sha512-xds1mkwEGzXrNy/gT6/ehaJ+cbYn/QM7AkdwNrO1NBlwJVLo3imO6hOnOQ/0KWG2ck1dbKv9H9f2hka67bAzEA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.956.0", + "@aws-sdk/core": "3.957.0", "@smithy/core": "^3.20.0", "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", @@ -1137,13 +853,13 @@ "node": ">=18.0.0" }, "peerDependencies": { - "@aws-sdk/client-dynamodb": "^3.956.0" + "@aws-sdk/client-dynamodb": "^3.957.0" } }, "node_modules/@aws-sdk/endpoint-cache": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.953.0.tgz", - "integrity": "sha512-pz67DoHk5WNmvMuyNDiomUS2xo0mq6Z3TdfLJZlWVbSKi3h8hYxVQchJ2kzgTr6wu6zt3UBbtKV9yY1IBhKMVA==", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.957.0.tgz", + "integrity": "sha512-QxvFejXYYBZp/GBfT7B15gvmvuq+0f2U8RPHqArf5IqBi51ZyBqUD805tQ8TlsVrlLoi+Z4fEFw4HEM5pGvPUg==", "license": "Apache-2.0", "dependencies": { "mnemonist": "0.38.3", @@ -1154,13 +870,13 @@ } }, "node_modules/@aws-sdk/lib-dynamodb": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.956.0.tgz", - "integrity": "sha512-RA21BJsFS3tqellTGURz0oqf/xGZcK2xUow9sXl17SaC8ukYvIsUyPf8q+RcCVsXVezKG9n6yJhEsHemnNjH5Q==", + "version": "3.958.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.958.0.tgz", + "integrity": "sha512-ojqEe4ojhk/MINaaEzqFLcZ9abBGP+zwUxTJh9x2mM2Y7Y4Gvqmwvs5aT790pI8yiPKPDkeF/E+DNEmSCUPtlA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.956.0", - "@aws-sdk/util-dynamodb": "3.956.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/util-dynamodb": "3.958.0", "@smithy/core": "^3.20.0", "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", @@ -1170,20 +886,20 @@ "node": ">=18.0.0" }, "peerDependencies": { - "@aws-sdk/client-dynamodb": "^3.956.0" + "@aws-sdk/client-dynamodb": "^3.958.0" } }, "node_modules/@aws-sdk/middleware-endpoint-discovery": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.953.0.tgz", - "integrity": "sha512-/YKB1/OiWr7TwOfmkqzv8x1xgOpU71yciQTfsq6erB3dTQhdukPADt/CMJOhWFKC6Q1D5cDN8381nsGmnNuBVg==", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.957.0.tgz", + "integrity": "sha512-MJjlw4mVJNTyR5dW6wpzKLRzFPIYAMA8qUWqgG4hGscmm4GFHvWVJ9mhhdpDu7Ie4Uaikmzfy0C4xzZ+lkf1+w==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/endpoint-cache": "3.953.0", - "@aws-sdk/types": "3.953.0", - "@smithy/node-config-provider": "^4.3.6", - "@smithy/protocol-http": "^5.3.6", - "@smithy/types": "^4.10.0", + "@aws-sdk/endpoint-cache": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/protocol-http": "^5.3.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -1191,14 +907,14 @@ } }, "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.953.0.tgz", - "integrity": "sha512-jTGhfkONav+r4E6HLOrl5SzBqDmPByUYCkyB/c/3TVb8jX3wAZx8/q9bphKpCh+G5ARi3IdbSisgkZrJYqQ19Q==", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.957.0.tgz", + "integrity": "sha512-BBgKawVyfQZglEkNTuBBdC3azlyqNXsvvN4jPkWAiNYcY0x1BasaJFl+7u/HisfULstryweJq/dAvIZIxzlZaA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.953.0", - "@smithy/protocol-http": "^5.3.6", - "@smithy/types": "^4.10.0", + "@aws-sdk/types": "3.957.0", + "@smithy/protocol-http": "^5.3.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -1206,13 +922,13 @@ } }, "node_modules/@aws-sdk/middleware-logger": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.953.0.tgz", - "integrity": "sha512-PlWdVYgcuptkIC0ZKqVUhWNtSHXJSx7U9V8J7dJjRmsXC40X7zpEycvrkzDMJjeTDGcCceYbyYAg/4X1lkcIMw==", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.957.0.tgz", + "integrity": "sha512-w1qfKrSKHf9b5a8O76yQ1t69u6NWuBjr5kBX+jRWFx/5mu6RLpqERXRpVJxfosbep7k3B+DSB5tZMZ82GKcJtQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.953.0", - "@smithy/types": "^4.10.0", + "@aws-sdk/types": "3.957.0", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -1220,31 +936,13 @@ } }, "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.953.0.tgz", - "integrity": "sha512-cmIJx0gWeesUKK4YwgE+VQL3mpACr3/J24fbwnc1Z5tntC86b+HQFzU5vsBDw6lLwyD46dBgWdsXFh1jL+ZaFw==", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.957.0.tgz", + "integrity": "sha512-D2H/WoxhAZNYX+IjkKTdOhOkWQaK0jjJrDBj56hKjU5c9ltQiaX/1PqJ4dfjHntEshJfu0w+E6XJ+/6A6ILBBA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.953.0", + "@aws-sdk/types": "3.957.0", "@aws/lambda-invoke-store": "^0.2.2", - "@smithy/protocol-http": "^5.3.6", - "@smithy/types": "^4.10.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.956.0.tgz", - "integrity": "sha512-azH8OJ0AIe3NafaTNvJorG/ALaLNTYwVKtyaSeQKOvaL8TNuBVuDnM5iHCiWryIaRgZotomqycwyfNKLw2D3JQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.956.0", - "@aws-sdk/types": "3.956.0", - "@aws-sdk/util-endpoints": "3.956.0", - "@smithy/core": "^3.20.0", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" @@ -1253,29 +951,35 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/middleware-user-agent/node_modules/@aws-sdk/types": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", - "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", + "node_modules/@aws-sdk/middleware-sdk-sqs": { + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sqs/-/middleware-sdk-sqs-3.957.0.tgz", + "integrity": "sha512-3A1V2oSV/NzWukwDBwnf/ng+n+8zU32jRml0lbYiP9PzBgc6D6Y4Z/RCbPp7g+PO8XrCRrZg6QKspO3cLpGnOw==", "license": "Apache-2.0", "dependencies": { + "@aws-sdk/types": "3.957.0", + "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", + "@smithy/util-hex-encoding": "^4.2.0", + "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/middleware-user-agent/node_modules/@aws-sdk/util-endpoints": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.956.0.tgz", - "integrity": "sha512-xZ5CBoubS4rs9JkFniKNShDtfqxaMUnwaebYMoybZm070q9+omFkQkJYXl7kopTViEgZgQl1sAsAkrawBM8qEQ==", + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.957.0.tgz", + "integrity": "sha512-50vcHu96XakQnIvlKJ1UoltrFODjsq2KvtTgHiPFteUS884lQnK5VC/8xd1Msz/1ONpLMzdCVproCQqhDTtMPQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.956.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@aws-sdk/util-endpoints": "3.957.0", + "@smithy/core": "^3.20.0", + "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", - "@smithy/url-parser": "^4.2.7", - "@smithy/util-endpoints": "^3.2.7", "tslib": "^2.6.2" }, "engines": { @@ -1283,23 +987,23 @@ } }, "node_modules/@aws-sdk/nested-clients": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.956.0.tgz", - "integrity": "sha512-GHDQMkxoWpi3eTrhWGmghw0gsZJ5rM1ERHfBFhlhduCdtV3TyhKVmDgFG84KhU8v18dcVpSp3Pu3KwH7j1tgIg==", + "version": "3.958.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.958.0.tgz", + "integrity": "sha512-/KuCcS8b5TpQXkYOrPLYytrgxBhv81+5pChkOlhegbeHttjM69pyUpQVJqyfDM/A7wPLnDrzCAnk4zaAOkY0Nw==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.956.0", - "@aws-sdk/middleware-host-header": "3.956.0", - "@aws-sdk/middleware-logger": "3.956.0", - "@aws-sdk/middleware-recursion-detection": "3.956.0", - "@aws-sdk/middleware-user-agent": "3.956.0", - "@aws-sdk/region-config-resolver": "3.956.0", - "@aws-sdk/types": "3.956.0", - "@aws-sdk/util-endpoints": "3.956.0", - "@aws-sdk/util-user-agent-browser": "3.956.0", - "@aws-sdk/util-user-agent-node": "3.956.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/middleware-host-header": "3.957.0", + "@aws-sdk/middleware-logger": "3.957.0", + "@aws-sdk/middleware-recursion-detection": "3.957.0", + "@aws-sdk/middleware-user-agent": "3.957.0", + "@aws-sdk/region-config-resolver": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@aws-sdk/util-endpoints": "3.957.0", + "@aws-sdk/util-user-agent-browser": "3.957.0", + "@aws-sdk/util-user-agent-node": "3.957.0", "@smithy/config-resolver": "^4.4.5", "@smithy/core": "^3.20.0", "@smithy/fetch-http-handler": "^5.3.8", @@ -1313,136 +1017,34 @@ "@smithy/node-config-provider": "^4.3.7", "@smithy/node-http-handler": "^4.4.7", "@smithy/protocol-http": "^5.3.7", - "@smithy/smithy-client": "^4.10.2", - "@smithy/types": "^4.11.0", - "@smithy/url-parser": "^4.2.7", - "@smithy/util-base64": "^4.3.0", - "@smithy/util-body-length-browser": "^4.2.0", - "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.16", - "@smithy/util-defaults-mode-node": "^4.2.19", - "@smithy/util-endpoints": "^3.2.7", - "@smithy/util-middleware": "^4.2.7", - "@smithy/util-retry": "^4.2.7", - "@smithy/util-utf8": "^4.2.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/middleware-host-header": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.956.0.tgz", - "integrity": "sha512-JujNJDp/dj1DbsI0ntzhrz2uJ4jpumcKtr743eMpEhdboYjuu/UzY8/7n1h5JbgU9TNXgqE9lgQNa5QPG0Tvsg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.956.0", - "@smithy/protocol-http": "^5.3.7", - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/middleware-logger": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.956.0.tgz", - "integrity": "sha512-Qff39yEOPYgRsm4SrkHOvS0nSoxXILYnC8Akp0uMRi2lOcZVyXL3WCWqIOtI830qVI4GPa796sleKguxx50RHg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.956.0", - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.956.0.tgz", - "integrity": "sha512-/f4JxL2kSCYhy63wovqts6SJkpalSLvuFe78ozt3ClrGoHGyr69o7tPRYx5U7azLgvrIGjsWUyTayeAk3YHIVQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.956.0", - "@aws/lambda-invoke-store": "^0.2.2", - "@smithy/protocol-http": "^5.3.7", - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/region-config-resolver": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.956.0.tgz", - "integrity": "sha512-byU5XYekW7+rZ3e067y038wlrpnPkdI4fMxcHCHrv+TAfzl8CCk5xLyzerQtXZR8cVPVOXuaYWe1zKW0uCnXUA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.956.0", - "@smithy/config-resolver": "^4.4.5", - "@smithy/node-config-provider": "^4.3.7", - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/types": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", - "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/util-endpoints": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.956.0.tgz", - "integrity": "sha512-xZ5CBoubS4rs9JkFniKNShDtfqxaMUnwaebYMoybZm070q9+omFkQkJYXl7kopTViEgZgQl1sAsAkrawBM8qEQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.956.0", + "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.16", + "@smithy/util-defaults-mode-node": "^4.2.19", "@smithy/util-endpoints": "^3.2.7", + "@smithy/util-middleware": "^4.2.7", + "@smithy/util-retry": "^4.2.7", + "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/nested-clients/node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.956.0.tgz", - "integrity": "sha512-s8KwYR3HqiGNni7a1DN2P3RUog64QoBQ6VCSzJkHBWb6++8KSOpqeeDkfmEz+22y1LOne+bRrpDGKa0aqOc3rQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/types": "3.956.0", - "@smithy/types": "^4.11.0", - "bowser": "^2.11.0", - "tslib": "^2.6.2" - } - }, "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.953.0.tgz", - "integrity": "sha512-5MJgnsc+HLO+le0EK1cy92yrC7kyhGZSpaq8PcQvKs9qtXCXT5Tb6tMdkr5Y07JxYsYOV1omWBynvL6PWh08tQ==", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.957.0.tgz", + "integrity": "sha512-V8iY3blh8l2iaOqXWW88HbkY5jDoWjH56jonprG/cpyqqCnprvpMUZWPWYJoI8rHRf2bqzZeql1slxG6EnKI7A==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.953.0", - "@smithy/config-resolver": "^4.4.4", - "@smithy/node-config-provider": "^4.3.6", - "@smithy/types": "^4.10.0", + "@aws-sdk/types": "3.957.0", + "@smithy/config-resolver": "^4.4.5", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -1450,14 +1052,14 @@ } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.956.0.tgz", - "integrity": "sha512-I01Q9yDeG9oXge14u/bubtSdBpok/rTsPp2AQwy5xj/5PatRTHPbUTP6tef3AH/lFCAqkI0nncIcgx6zikDdUQ==", + "version": "3.958.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.958.0.tgz", + "integrity": "sha512-UCj7lQXODduD1myNJQkV+LYcGYJ9iiMggR8ow8Hva1g3A/Na5imNXzz6O67k7DAee0TYpy+gkNw+SizC6min8Q==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.956.0", - "@aws-sdk/nested-clients": "3.956.0", - "@aws-sdk/types": "3.956.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/nested-clients": "3.958.0", + "@aws-sdk/types": "3.957.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", @@ -1467,26 +1069,13 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/token-providers/node_modules/@aws-sdk/types": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", - "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/types": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.953.0.tgz", - "integrity": "sha512-M9Iwg9kTyqTErI0vOTVVpcnTHWzS3VplQppy8MuL02EE+mJ0BIwpWfsaAPQW+/XnVpdNpWZTsHcNE29f1+hR8g==", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.957.0.tgz", + "integrity": "sha512-wzWC2Nrt859ABk6UCAVY/WYEbAd7FjkdrQL6m24+tfmWYDNRByTJ9uOgU/kw9zqLCAwb//CPvrJdhqjTznWXAg==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.10.0", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -1494,9 +1083,9 @@ } }, "node_modules/@aws-sdk/util-dynamodb": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.956.0.tgz", - "integrity": "sha512-RZrYUZ9zacb7t2+CeD+/UkVriIQ3N4MyQi+f/KPEbqZ1mYg1yXo/kFvUL4Qdi28qve/pG3J3R1tx9eb6nMW1uQ==", + "version": "3.958.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.958.0.tgz", + "integrity": "sha512-wNGCmCBaj+Om4e93+zkiWv7L+sPGlJuDKHWpndCLdHp3EyHt46KxQpAC5QOMTzbRS0obxl2LqXilX8fbQZxU6A==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -1505,19 +1094,19 @@ "node": ">=18.0.0" }, "peerDependencies": { - "@aws-sdk/client-dynamodb": "^3.956.0" + "@aws-sdk/client-dynamodb": "^3.958.0" } }, "node_modules/@aws-sdk/util-endpoints": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.953.0.tgz", - "integrity": "sha512-rjaS6jrFksopXvNg6YeN+D1lYwhcByORNlFuYesFvaQNtPOufbE5tJL4GJ3TMXyaY0uFR28N5BHHITPyWWfH/g==", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.957.0.tgz", + "integrity": "sha512-xwF9K24mZSxcxKS3UKQFeX/dPYkEps9wF1b+MGON7EvnbcucrJGyQyK1v1xFPn1aqXkBTFi+SZaMRx5E5YCVFw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.953.0", - "@smithy/types": "^4.10.0", - "@smithy/url-parser": "^4.2.6", - "@smithy/util-endpoints": "^3.2.6", + "@aws-sdk/types": "3.957.0", + "@smithy/types": "^4.11.0", + "@smithy/url-parser": "^4.2.7", + "@smithy/util-endpoints": "^3.2.7", "tslib": "^2.6.2" }, "engines": { @@ -1525,9 +1114,9 @@ } }, "node_modules/@aws-sdk/util-locate-window": { - "version": "3.893.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.893.0.tgz", - "integrity": "sha512-T89pFfgat6c8nMmpI8eKjBcDcgJq36+m9oiXbcUzeU55MP9ZuGgBomGjGnHaEyF36jenW9gmg3NfZDm0AO2XPg==", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.957.0.tgz", + "integrity": "sha512-nhmgKHnNV9K+i9daumaIz8JTLsIIML9PE/HUks5liyrjUzenjW/aHoc7WJ9/Td/gPZtayxFnXQSJRb/fDlBuJw==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -1537,25 +1126,25 @@ } }, "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.953.0.tgz", - "integrity": "sha512-UF5NeqYesWuFao+u7LJvpV1SJCaLml5BtFZKUdTnNNMeN6jvV+dW/eQoFGpXF94RCqguX0XESmRuRRPQp+/rzQ==", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.957.0.tgz", + "integrity": "sha512-exueuwxef0lUJRnGaVkNSC674eAiWU07ORhxBnevFFZEKisln+09Qrtw823iyv5I1N8T+wKfh95xvtWQrNKNQw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.953.0", - "@smithy/types": "^4.10.0", + "@aws-sdk/types": "3.957.0", + "@smithy/types": "^4.11.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.956.0.tgz", - "integrity": "sha512-H0r6ol3Rr63/3xvrUsLqHps+cA7VkM7uCU5NtuTHnMbv3uYYTKf9M2XFHAdVewmmRgssTzvqemrARc8Ji3SNvg==", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.957.0.tgz", + "integrity": "sha512-ycbYCwqXk4gJGp0Oxkzf2KBeeGBdTxz559D41NJP8FlzSej1Gh7Rk40Zo6AyTfsNWkrl/kVi1t937OIzC5t+9Q==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-user-agent": "3.956.0", - "@aws-sdk/types": "3.956.0", + "@aws-sdk/middleware-user-agent": "3.957.0", + "@aws-sdk/types": "3.957.0", "@smithy/node-config-provider": "^4.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" @@ -1572,26 +1161,13 @@ } } }, - "node_modules/@aws-sdk/util-user-agent-node/node_modules/@aws-sdk/types": { - "version": "3.956.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.956.0.tgz", - "integrity": "sha512-DMRU/p9wAlAJxEjegnLwduCA8YP2pcT/sIJ+17KSF38c5cC6CbBhykwbZLECTo+zYzoFrOqeLbqE6paH8Gx3ug==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/xml-builder": { - "version": "3.953.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.953.0.tgz", - "integrity": "sha512-Zmrj21jQ2OeOJGr9spPiN00aQvXa/WUqRXcTVENhrMt+OFoSOfDFpYhUj9NQ09QmQ8KMWFoWuWW6iKurNqLvAA==", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.957.0.tgz", + "integrity": "sha512-Ai5iiQqS8kJ5PjzMhWcLKN0G2yasAkvpnPlq2EnqlIMdB48HsizElt62qcktdxp4neRMyGkFq4NzgmDbXnhRiA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.10.0", + "@smithy/types": "^4.11.0", "fast-xml-parser": "5.2.5", "tslib": "^2.6.2" }, @@ -2988,138 +2564,173 @@ } }, "node_modules/@leanstacks/lambda-utils": { - "version": "0.3.0-alpha.4", - "resolved": "https://registry.npmjs.org/@leanstacks/lambda-utils/-/lambda-utils-0.3.0-alpha.4.tgz", - "integrity": "sha512-RUs2RkhEr7djdQy5EjhWDHLpyCsxmc/P4p6tBMPQZE5KVTzebRFRiXKh2MGZJ5teOjeV8Xtwa7Fi2h2STujXDw==", + "version": "0.4.0-alpha.1", + "resolved": "https://registry.npmjs.org/@leanstacks/lambda-utils/-/lambda-utils-0.4.0-alpha.1.tgz", + "integrity": "sha512-q+xvGG56BWpRaODNOv+nO3uDGag81b/z+z8+TnUrohs40LDrsDBVvU6lLlYDBoSl8MpLZODuxSNT5cB0g9R6DA==", "license": "MIT", "dependencies": { - "@aws-sdk/client-dynamodb": "3.955.0", - "@aws-sdk/lib-dynamodb": "3.955.0", + "@aws-sdk/client-dynamodb": "3.957.0", + "@aws-sdk/client-lambda": "3.957.0", + "@aws-sdk/client-sns": "3.957.0", + "@aws-sdk/client-sqs": "3.957.0", + "@aws-sdk/lib-dynamodb": "3.957.0", "pino": "10.1.0", "pino-lambda": "4.4.1", "zod": "4.2.1" } }, "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/client-dynamodb": { - "version": "3.955.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.955.0.tgz", - "integrity": "sha512-Qo1Sv6rKxRCecaKOsdjwbeYvnmlVyueaNP5/DmAzdbxVI7pGsIFUqCXQYA0jwfONwoMoMwf/PsyGaW/+9nGhhQ==", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.957.0.tgz", + "integrity": "sha512-H/uHYgZTmFUq2qb4b/GTxT2F8Yyqyb3pMpI3mldGINZkPYQYN9pP246pqnf+OYOClPMxSMRchrbjZgZhADMi8Q==", "license": "Apache-2.0", "peer": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.954.0", - "@aws-sdk/credential-provider-node": "3.955.0", - "@aws-sdk/dynamodb-codec": "3.954.0", - "@aws-sdk/middleware-endpoint-discovery": "3.953.0", - "@aws-sdk/middleware-host-header": "3.953.0", - "@aws-sdk/middleware-logger": "3.953.0", - "@aws-sdk/middleware-recursion-detection": "3.953.0", - "@aws-sdk/middleware-user-agent": "3.954.0", - "@aws-sdk/region-config-resolver": "3.953.0", - "@aws-sdk/types": "3.953.0", - "@aws-sdk/util-endpoints": "3.953.0", - "@aws-sdk/util-user-agent-browser": "3.953.0", - "@aws-sdk/util-user-agent-node": "3.954.0", - "@smithy/config-resolver": "^4.4.4", - "@smithy/core": "^3.19.0", - "@smithy/fetch-http-handler": "^5.3.7", - "@smithy/hash-node": "^4.2.6", - "@smithy/invalid-dependency": "^4.2.6", - "@smithy/middleware-content-length": "^4.2.6", - "@smithy/middleware-endpoint": "^4.4.0", - "@smithy/middleware-retry": "^4.4.16", - "@smithy/middleware-serde": "^4.2.7", - "@smithy/middleware-stack": "^4.2.6", - "@smithy/node-config-provider": "^4.3.6", - "@smithy/node-http-handler": "^4.4.6", - "@smithy/protocol-http": "^5.3.6", - "@smithy/smithy-client": "^4.10.1", - "@smithy/types": "^4.10.0", - "@smithy/url-parser": "^4.2.6", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/credential-provider-node": "3.957.0", + "@aws-sdk/dynamodb-codec": "3.957.0", + "@aws-sdk/middleware-endpoint-discovery": "3.957.0", + "@aws-sdk/middleware-host-header": "3.957.0", + "@aws-sdk/middleware-logger": "3.957.0", + "@aws-sdk/middleware-recursion-detection": "3.957.0", + "@aws-sdk/middleware-user-agent": "3.957.0", + "@aws-sdk/region-config-resolver": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@aws-sdk/util-endpoints": "3.957.0", + "@aws-sdk/util-user-agent-browser": "3.957.0", + "@aws-sdk/util-user-agent-node": "3.957.0", + "@smithy/config-resolver": "^4.4.5", + "@smithy/core": "^3.20.0", + "@smithy/fetch-http-handler": "^5.3.8", + "@smithy/hash-node": "^4.2.7", + "@smithy/invalid-dependency": "^4.2.7", + "@smithy/middleware-content-length": "^4.2.7", + "@smithy/middleware-endpoint": "^4.4.1", + "@smithy/middleware-retry": "^4.4.17", + "@smithy/middleware-serde": "^4.2.8", + "@smithy/middleware-stack": "^4.2.7", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/node-http-handler": "^4.4.7", + "@smithy/protocol-http": "^5.3.7", + "@smithy/smithy-client": "^4.10.2", + "@smithy/types": "^4.11.0", + "@smithy/url-parser": "^4.2.7", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.15", - "@smithy/util-defaults-mode-node": "^4.2.18", - "@smithy/util-endpoints": "^3.2.6", - "@smithy/util-middleware": "^4.2.6", - "@smithy/util-retry": "^4.2.6", + "@smithy/util-defaults-mode-browser": "^4.3.16", + "@smithy/util-defaults-mode-node": "^4.2.19", + "@smithy/util-endpoints": "^3.2.7", + "@smithy/util-middleware": "^4.2.7", + "@smithy/util-retry": "^4.2.7", "@smithy/util-utf8": "^4.2.0", - "@smithy/util-waiter": "^4.2.6", + "@smithy/util-waiter": "^4.2.7", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/client-sso": { - "version": "3.955.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.955.0.tgz", - "integrity": "sha512-+nym5boDFt2ksba0fElocMKxCFJbJcd31PI3502hoI1N5VK7HyxkQeBtQJ64JYomvw8eARjWWC13hkB0LtZILw==", + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/client-lambda": { + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.957.0.tgz", + "integrity": "sha512-g7ZXBME+Um6ViY0y7HCGd8U1NlsbyZEQQe3dtw5jRcUl5zNAE76SxYKWkZo9GDdXzNqPJTFTjKlv18m4FyGJIA==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.954.0", - "@aws-sdk/middleware-host-header": "3.953.0", - "@aws-sdk/middleware-logger": "3.953.0", - "@aws-sdk/middleware-recursion-detection": "3.953.0", - "@aws-sdk/middleware-user-agent": "3.954.0", - "@aws-sdk/region-config-resolver": "3.953.0", - "@aws-sdk/types": "3.953.0", - "@aws-sdk/util-endpoints": "3.953.0", - "@aws-sdk/util-user-agent-browser": "3.953.0", - "@aws-sdk/util-user-agent-node": "3.954.0", - "@smithy/config-resolver": "^4.4.4", - "@smithy/core": "^3.19.0", - "@smithy/fetch-http-handler": "^5.3.7", - "@smithy/hash-node": "^4.2.6", - "@smithy/invalid-dependency": "^4.2.6", - "@smithy/middleware-content-length": "^4.2.6", - "@smithy/middleware-endpoint": "^4.4.0", - "@smithy/middleware-retry": "^4.4.16", - "@smithy/middleware-serde": "^4.2.7", - "@smithy/middleware-stack": "^4.2.6", - "@smithy/node-config-provider": "^4.3.6", - "@smithy/node-http-handler": "^4.4.6", - "@smithy/protocol-http": "^5.3.6", - "@smithy/smithy-client": "^4.10.1", - "@smithy/types": "^4.10.0", - "@smithy/url-parser": "^4.2.6", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/credential-provider-node": "3.957.0", + "@aws-sdk/middleware-host-header": "3.957.0", + "@aws-sdk/middleware-logger": "3.957.0", + "@aws-sdk/middleware-recursion-detection": "3.957.0", + "@aws-sdk/middleware-user-agent": "3.957.0", + "@aws-sdk/region-config-resolver": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@aws-sdk/util-endpoints": "3.957.0", + "@aws-sdk/util-user-agent-browser": "3.957.0", + "@aws-sdk/util-user-agent-node": "3.957.0", + "@smithy/config-resolver": "^4.4.5", + "@smithy/core": "^3.20.0", + "@smithy/eventstream-serde-browser": "^4.2.7", + "@smithy/eventstream-serde-config-resolver": "^4.3.7", + "@smithy/eventstream-serde-node": "^4.2.7", + "@smithy/fetch-http-handler": "^5.3.8", + "@smithy/hash-node": "^4.2.7", + "@smithy/invalid-dependency": "^4.2.7", + "@smithy/middleware-content-length": "^4.2.7", + "@smithy/middleware-endpoint": "^4.4.1", + "@smithy/middleware-retry": "^4.4.17", + "@smithy/middleware-serde": "^4.2.8", + "@smithy/middleware-stack": "^4.2.7", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/node-http-handler": "^4.4.7", + "@smithy/protocol-http": "^5.3.7", + "@smithy/smithy-client": "^4.10.2", + "@smithy/types": "^4.11.0", + "@smithy/url-parser": "^4.2.7", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.15", - "@smithy/util-defaults-mode-node": "^4.2.18", - "@smithy/util-endpoints": "^3.2.6", - "@smithy/util-middleware": "^4.2.6", - "@smithy/util-retry": "^4.2.6", + "@smithy/util-defaults-mode-browser": "^4.3.16", + "@smithy/util-defaults-mode-node": "^4.2.19", + "@smithy/util-endpoints": "^3.2.7", + "@smithy/util-middleware": "^4.2.7", + "@smithy/util-retry": "^4.2.7", + "@smithy/util-stream": "^4.5.8", "@smithy/util-utf8": "^4.2.0", + "@smithy/util-waiter": "^4.2.7", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/core": { - "version": "3.954.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.954.0.tgz", - "integrity": "sha512-5oYO5RP+mvCNXNj8XnF9jZo0EP0LTseYOJVNQYcii1D9DJqzHL3HJWurYh7cXxz7G7eDyvVYA01O9Xpt34TdoA==", + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/client-sns": { + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sns/-/client-sns-3.957.0.tgz", + "integrity": "sha512-edRPKM7u8rB4LBe+bv5xWcOlUMvlCH9kNT+fIa7YcSBzLYGHedE6pbgAwACwTUnBOoaKKPGZZ9Fm9o4ZD8/JXQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.953.0", - "@aws-sdk/xml-builder": "3.953.0", - "@smithy/core": "^3.19.0", - "@smithy/node-config-provider": "^4.3.6", - "@smithy/property-provider": "^4.2.6", - "@smithy/protocol-http": "^5.3.6", - "@smithy/signature-v4": "^5.3.6", - "@smithy/smithy-client": "^4.10.1", - "@smithy/types": "^4.10.0", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/credential-provider-node": "3.957.0", + "@aws-sdk/middleware-host-header": "3.957.0", + "@aws-sdk/middleware-logger": "3.957.0", + "@aws-sdk/middleware-recursion-detection": "3.957.0", + "@aws-sdk/middleware-user-agent": "3.957.0", + "@aws-sdk/region-config-resolver": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@aws-sdk/util-endpoints": "3.957.0", + "@aws-sdk/util-user-agent-browser": "3.957.0", + "@aws-sdk/util-user-agent-node": "3.957.0", + "@smithy/config-resolver": "^4.4.5", + "@smithy/core": "^3.20.0", + "@smithy/fetch-http-handler": "^5.3.8", + "@smithy/hash-node": "^4.2.7", + "@smithy/invalid-dependency": "^4.2.7", + "@smithy/middleware-content-length": "^4.2.7", + "@smithy/middleware-endpoint": "^4.4.1", + "@smithy/middleware-retry": "^4.4.17", + "@smithy/middleware-serde": "^4.2.8", + "@smithy/middleware-stack": "^4.2.7", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/node-http-handler": "^4.4.7", + "@smithy/protocol-http": "^5.3.7", + "@smithy/smithy-client": "^4.10.2", + "@smithy/types": "^4.11.0", + "@smithy/url-parser": "^4.2.7", "@smithy/util-base64": "^4.3.0", - "@smithy/util-middleware": "^4.2.6", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.16", + "@smithy/util-defaults-mode-node": "^4.2.19", + "@smithy/util-endpoints": "^3.2.7", + "@smithy/util-middleware": "^4.2.7", + "@smithy/util-retry": "^4.2.7", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" }, @@ -3127,37 +2738,49 @@ "node": ">=18.0.0" } }, - "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/credential-provider-env": { - "version": "3.954.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.954.0.tgz", - "integrity": "sha512-2HNkqBjfsvyoRuPAiFh86JBFMFyaCNhL4VyH6XqwTGKZffjG7hdBmzXPy7AT7G3oFh1k/1Zc27v0qxaKoK7mBA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.954.0", - "@aws-sdk/types": "3.953.0", - "@smithy/property-provider": "^4.2.6", - "@smithy/types": "^4.10.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/credential-provider-http": { - "version": "3.954.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.954.0.tgz", - "integrity": "sha512-CrWD5300+NE1OYRnSVDxoG7G0b5cLIZb7yp+rNQ5Jq/kqnTmyJXpVAsivq+bQIDaGzPXhadzpAMIoo7K/aHaag==", + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/client-sso": { + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.957.0.tgz", + "integrity": "sha512-iRdRjd+IpOogqRPt8iNRcg30J53z4rRfMviGwpKgsEa/fx3inCUPOuca3Ap7ZDES0atnEg3KGSJ3V/NQiEJ4BA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.954.0", - "@aws-sdk/types": "3.953.0", - "@smithy/fetch-http-handler": "^5.3.7", - "@smithy/node-http-handler": "^4.4.6", - "@smithy/property-provider": "^4.2.6", - "@smithy/protocol-http": "^5.3.6", - "@smithy/smithy-client": "^4.10.1", - "@smithy/types": "^4.10.0", - "@smithy/util-stream": "^4.5.7", + "@aws-crypto/sha256-browser": "5.2.0", + "@aws-crypto/sha256-js": "5.2.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/middleware-host-header": "3.957.0", + "@aws-sdk/middleware-logger": "3.957.0", + "@aws-sdk/middleware-recursion-detection": "3.957.0", + "@aws-sdk/middleware-user-agent": "3.957.0", + "@aws-sdk/region-config-resolver": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@aws-sdk/util-endpoints": "3.957.0", + "@aws-sdk/util-user-agent-browser": "3.957.0", + "@aws-sdk/util-user-agent-node": "3.957.0", + "@smithy/config-resolver": "^4.4.5", + "@smithy/core": "^3.20.0", + "@smithy/fetch-http-handler": "^5.3.8", + "@smithy/hash-node": "^4.2.7", + "@smithy/invalid-dependency": "^4.2.7", + "@smithy/middleware-content-length": "^4.2.7", + "@smithy/middleware-endpoint": "^4.4.1", + "@smithy/middleware-retry": "^4.4.17", + "@smithy/middleware-serde": "^4.2.8", + "@smithy/middleware-stack": "^4.2.7", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/node-http-handler": "^4.4.7", + "@smithy/protocol-http": "^5.3.7", + "@smithy/smithy-client": "^4.10.2", + "@smithy/types": "^4.11.0", + "@smithy/url-parser": "^4.2.7", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-body-length-browser": "^4.2.0", + "@smithy/util-body-length-node": "^4.2.1", + "@smithy/util-defaults-mode-browser": "^4.3.16", + "@smithy/util-defaults-mode-node": "^4.2.19", + "@smithy/util-endpoints": "^3.2.7", + "@smithy/util-middleware": "^4.2.7", + "@smithy/util-retry": "^4.2.7", + "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" }, "engines": { @@ -3165,24 +2788,24 @@ } }, "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.955.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.955.0.tgz", - "integrity": "sha512-90isLovxsPzaaSx3IIUZuxym6VXrsRetnQ3AuHr2kiTFk2pIzyIwmi+gDcUaLXQ5nNBoSj1Z/4+i1vhxa1n2DQ==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.954.0", - "@aws-sdk/credential-provider-env": "3.954.0", - "@aws-sdk/credential-provider-http": "3.954.0", - "@aws-sdk/credential-provider-login": "3.955.0", - "@aws-sdk/credential-provider-process": "3.954.0", - "@aws-sdk/credential-provider-sso": "3.955.0", - "@aws-sdk/credential-provider-web-identity": "3.955.0", - "@aws-sdk/nested-clients": "3.955.0", - "@aws-sdk/types": "3.953.0", - "@smithy/credential-provider-imds": "^4.2.6", - "@smithy/property-provider": "^4.2.6", - "@smithy/shared-ini-file-loader": "^4.4.1", - "@smithy/types": "^4.10.0", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.957.0.tgz", + "integrity": "sha512-YuoZmIeE91YIeUfihh8SiSu546KtTvU+4rG5SaL30U9+nGq6P11GRRgqF0ANUyRseLC9ONHt+utar4gbO3++og==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "3.957.0", + "@aws-sdk/credential-provider-env": "3.957.0", + "@aws-sdk/credential-provider-http": "3.957.0", + "@aws-sdk/credential-provider-login": "3.957.0", + "@aws-sdk/credential-provider-process": "3.957.0", + "@aws-sdk/credential-provider-sso": "3.957.0", + "@aws-sdk/credential-provider-web-identity": "3.957.0", + "@aws-sdk/nested-clients": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@smithy/credential-provider-imds": "^4.2.7", + "@smithy/property-provider": "^4.2.7", + "@smithy/shared-ini-file-loader": "^4.4.2", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -3190,201 +2813,146 @@ } }, "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/credential-provider-login": { - "version": "3.955.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.955.0.tgz", - "integrity": "sha512-xlkmSvg8oDN5LIxLAq3N1QWK8F8gUAsBWZlp1IX8Lr5XhcKI3GVarIIUcZrvCy1NjzCd/LDXYdNL6MRlNP4bAw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.954.0", - "@aws-sdk/nested-clients": "3.955.0", - "@aws-sdk/types": "3.953.0", - "@smithy/property-provider": "^4.2.6", - "@smithy/protocol-http": "^5.3.6", - "@smithy/shared-ini-file-loader": "^4.4.1", - "@smithy/types": "^4.10.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/credential-provider-node": { - "version": "3.955.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.955.0.tgz", - "integrity": "sha512-XIL4QB+dPOJA6DRTmYZL52wFcLTslb7V1ydS4FCNT2DVLhkO4ExkPP+pe5YmIpzt/Our1ugS+XxAs3e6BtyFjA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.954.0", - "@aws-sdk/credential-provider-http": "3.954.0", - "@aws-sdk/credential-provider-ini": "3.955.0", - "@aws-sdk/credential-provider-process": "3.954.0", - "@aws-sdk/credential-provider-sso": "3.955.0", - "@aws-sdk/credential-provider-web-identity": "3.955.0", - "@aws-sdk/types": "3.953.0", - "@smithy/credential-provider-imds": "^4.2.6", - "@smithy/property-provider": "^4.2.6", - "@smithy/shared-ini-file-loader": "^4.4.1", - "@smithy/types": "^4.10.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/credential-provider-process": { - "version": "3.954.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.954.0.tgz", - "integrity": "sha512-Y1/0O2LgbKM8iIgcVj/GNEQW6p90LVTCOzF2CI1pouoKqxmZ/1F7F66WHoa6XUOfKaCRj/R6nuMR3om9ThaM5A==", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.957.0.tgz", + "integrity": "sha512-XcD5NEQDWYk8B4gs89bkwf2d+DNF8oS2NR5RoHJEbX4l8KErVATUjpEYVn6/rAFEktungxlYTnQ5wh0cIQvP5w==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.954.0", - "@aws-sdk/types": "3.953.0", - "@smithy/property-provider": "^4.2.6", - "@smithy/shared-ini-file-loader": "^4.4.1", - "@smithy/types": "^4.10.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/nested-clients": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@smithy/property-provider": "^4.2.7", + "@smithy/protocol-http": "^5.3.7", + "@smithy/shared-ini-file-loader": "^4.4.2", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.955.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.955.0.tgz", - "integrity": "sha512-Y99KI73Fn8JnB4RY5Ls6j7rd5jmFFwnY9WLHIWeJdc+vfwL6Bb1uWKW3+m/B9+RC4Xoz2nQgtefBcdWq5Xx8iw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/client-sso": "3.955.0", - "@aws-sdk/core": "3.954.0", - "@aws-sdk/token-providers": "3.955.0", - "@aws-sdk/types": "3.953.0", - "@smithy/property-provider": "^4.2.6", - "@smithy/shared-ini-file-loader": "^4.4.1", - "@smithy/types": "^4.10.0", + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/credential-provider-node": { + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.957.0.tgz", + "integrity": "sha512-b9FT/7BQcJ001w+3JbTiJXfxHrWvPb7zDvvC1i1FKcNOvyCt3BGu04n4nO/b71a3iBnbfBXI89hCIZQsuLcEgw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.957.0", + "@aws-sdk/credential-provider-http": "3.957.0", + "@aws-sdk/credential-provider-ini": "3.957.0", + "@aws-sdk/credential-provider-process": "3.957.0", + "@aws-sdk/credential-provider-sso": "3.957.0", + "@aws-sdk/credential-provider-web-identity": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@smithy/credential-provider-imds": "^4.2.7", + "@smithy/property-provider": "^4.2.7", + "@smithy/shared-ini-file-loader": "^4.4.2", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.955.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.955.0.tgz", - "integrity": "sha512-+lFxkZ2Vz3qp/T68ZONKzWVTQvomTu7E6tts1dfAbEcDt62Y/nPCByq/C2hQj+TiN05HrUx+yTJaGHBklhkbqA==", + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.957.0.tgz", + "integrity": "sha512-gTLPJFOkGtn3tVGglRhCar2oOobK1YctZRAT8nfJr17uaSRoAP46zIIHNYBZZUMqImb0qAHD9Ugm+Zd9sIqxyA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.954.0", - "@aws-sdk/nested-clients": "3.955.0", - "@aws-sdk/types": "3.953.0", - "@smithy/property-provider": "^4.2.6", - "@smithy/shared-ini-file-loader": "^4.4.1", - "@smithy/types": "^4.10.0", + "@aws-sdk/client-sso": "3.957.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/token-providers": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@smithy/property-provider": "^4.2.7", + "@smithy/shared-ini-file-loader": "^4.4.2", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" } }, - "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/dynamodb-codec": { - "version": "3.954.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/dynamodb-codec/-/dynamodb-codec-3.954.0.tgz", - "integrity": "sha512-fNY0L1l9e36pLJef4NY5k7Q1SJnm5rgLSxSRPT8xL+bhQBtEn2E2t4JdBiTqlxgeyuOrafWOawbg8yS3pRPcLw==", + "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.957.0.tgz", + "integrity": "sha512-x17xMeD7c+rKEsWachGIMifACqkugskrETWz18QDWismFcrmUuOcZu5rUa8s9y1pnITLKUQ1xU/qDLPH52jLlA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.954.0", - "@smithy/core": "^3.19.0", - "@smithy/smithy-client": "^4.10.1", - "@smithy/types": "^4.10.0", - "@smithy/util-base64": "^4.3.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/nested-clients": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@smithy/property-provider": "^4.2.7", + "@smithy/shared-ini-file-loader": "^4.4.2", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-dynamodb": "^3.954.0" } }, "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/lib-dynamodb": { - "version": "3.955.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.955.0.tgz", - "integrity": "sha512-THm4It0gSWTQZDK+I7J/D1FmoNGXDHRpeYrnJ1uYx2z4TSWc8qqqHN2L/x3W8HtRITMUNUolCZI4tIz9zxdOow==", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.957.0.tgz", + "integrity": "sha512-v/GnmDIFfqDQub4tEp/QtsWOMMvSilMbbhCv0l5rPV9sd1NUmCtrH8iBHqVKeEmwSsiCzEKNTakmxSUJszrEww==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.954.0", - "@aws-sdk/util-dynamodb": "3.955.0", - "@smithy/core": "^3.19.0", - "@smithy/smithy-client": "^4.10.1", - "@smithy/types": "^4.10.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/util-dynamodb": "3.957.0", + "@smithy/core": "^3.20.0", + "@smithy/smithy-client": "^4.10.2", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" }, "peerDependencies": { - "@aws-sdk/client-dynamodb": "^3.955.0" - } - }, - "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.954.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.954.0.tgz", - "integrity": "sha512-5PX8JDe3dB2+MqXeGIhmgFnm2rbVsSxhz+Xyuu1oxLtbOn+a9UDA+sNBufEBjt3UxWy5qwEEY1fxdbXXayjlGg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "3.954.0", - "@aws-sdk/types": "3.953.0", - "@aws-sdk/util-endpoints": "3.953.0", - "@smithy/core": "^3.19.0", - "@smithy/protocol-http": "^5.3.6", - "@smithy/types": "^4.10.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" + "@aws-sdk/client-dynamodb": "^3.957.0" } }, "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/nested-clients": { - "version": "3.955.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.955.0.tgz", - "integrity": "sha512-RBi6CQHbPF09kqXAoiEOOPkVnSoU5YppKoOt/cgsWfoMHwC+7itIrEv+yRD62h14jIjF3KngVIQIrBRbX3o3/Q==", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.957.0.tgz", + "integrity": "sha512-PZUFtaUTSZWO+mbgQGWSiwz3EqedsuKNb7Xoxjzh5rfJE352DD4/jScQEhVPxvdLw62IK9b5UDu5kZlxzBs9Ow==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.954.0", - "@aws-sdk/middleware-host-header": "3.953.0", - "@aws-sdk/middleware-logger": "3.953.0", - "@aws-sdk/middleware-recursion-detection": "3.953.0", - "@aws-sdk/middleware-user-agent": "3.954.0", - "@aws-sdk/region-config-resolver": "3.953.0", - "@aws-sdk/types": "3.953.0", - "@aws-sdk/util-endpoints": "3.953.0", - "@aws-sdk/util-user-agent-browser": "3.953.0", - "@aws-sdk/util-user-agent-node": "3.954.0", - "@smithy/config-resolver": "^4.4.4", - "@smithy/core": "^3.19.0", - "@smithy/fetch-http-handler": "^5.3.7", - "@smithy/hash-node": "^4.2.6", - "@smithy/invalid-dependency": "^4.2.6", - "@smithy/middleware-content-length": "^4.2.6", - "@smithy/middleware-endpoint": "^4.4.0", - "@smithy/middleware-retry": "^4.4.16", - "@smithy/middleware-serde": "^4.2.7", - "@smithy/middleware-stack": "^4.2.6", - "@smithy/node-config-provider": "^4.3.6", - "@smithy/node-http-handler": "^4.4.6", - "@smithy/protocol-http": "^5.3.6", - "@smithy/smithy-client": "^4.10.1", - "@smithy/types": "^4.10.0", - "@smithy/url-parser": "^4.2.6", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/middleware-host-header": "3.957.0", + "@aws-sdk/middleware-logger": "3.957.0", + "@aws-sdk/middleware-recursion-detection": "3.957.0", + "@aws-sdk/middleware-user-agent": "3.957.0", + "@aws-sdk/region-config-resolver": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@aws-sdk/util-endpoints": "3.957.0", + "@aws-sdk/util-user-agent-browser": "3.957.0", + "@aws-sdk/util-user-agent-node": "3.957.0", + "@smithy/config-resolver": "^4.4.5", + "@smithy/core": "^3.20.0", + "@smithy/fetch-http-handler": "^5.3.8", + "@smithy/hash-node": "^4.2.7", + "@smithy/invalid-dependency": "^4.2.7", + "@smithy/middleware-content-length": "^4.2.7", + "@smithy/middleware-endpoint": "^4.4.1", + "@smithy/middleware-retry": "^4.4.17", + "@smithy/middleware-serde": "^4.2.8", + "@smithy/middleware-stack": "^4.2.7", + "@smithy/node-config-provider": "^4.3.7", + "@smithy/node-http-handler": "^4.4.7", + "@smithy/protocol-http": "^5.3.7", + "@smithy/smithy-client": "^4.10.2", + "@smithy/types": "^4.11.0", + "@smithy/url-parser": "^4.2.7", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.15", - "@smithy/util-defaults-mode-node": "^4.2.18", - "@smithy/util-endpoints": "^3.2.6", - "@smithy/util-middleware": "^4.2.6", - "@smithy/util-retry": "^4.2.6", + "@smithy/util-defaults-mode-browser": "^4.3.16", + "@smithy/util-defaults-mode-node": "^4.2.19", + "@smithy/util-endpoints": "^3.2.7", + "@smithy/util-middleware": "^4.2.7", + "@smithy/util-retry": "^4.2.7", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" }, @@ -3393,17 +2961,17 @@ } }, "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/token-providers": { - "version": "3.955.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.955.0.tgz", - "integrity": "sha512-LVpWkxXvMPgZofP2Gc8XBfQhsyecBMVARDHWMvks6vPbCLSTM7dw6H1HI9qbGNCurYcyc2xBRAkEDhChQlbPPg==", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.957.0.tgz", + "integrity": "sha512-oSwo3BZ6gcvhjTg036V0UQmtENUeNwfCU35iDckX961CdI1alQ3TKRWLzKrwvXCbrOx+bZsuA1PHsTbNhI/+Fw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.954.0", - "@aws-sdk/nested-clients": "3.955.0", - "@aws-sdk/types": "3.953.0", - "@smithy/property-provider": "^4.2.6", - "@smithy/shared-ini-file-loader": "^4.4.1", - "@smithy/types": "^4.10.0", + "@aws-sdk/core": "3.957.0", + "@aws-sdk/nested-clients": "3.957.0", + "@aws-sdk/types": "3.957.0", + "@smithy/property-provider": "^4.2.7", + "@smithy/shared-ini-file-loader": "^4.4.2", + "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "engines": { @@ -3411,42 +2979,18 @@ } }, "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/util-dynamodb": { - "version": "3.955.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.955.0.tgz", - "integrity": "sha512-X/gSn2fIv9G5JshUzuZmAp30C5IhjdZpfsF/5476wDDse7GnqIe8SfH7Q4MVFcdd08fTT9nPFETEnMc8ga5WHg==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@aws-sdk/client-dynamodb": "^3.955.0" - } - }, - "node_modules/@leanstacks/lambda-utils/node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.954.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.954.0.tgz", - "integrity": "sha512-fB5S5VOu7OFkeNzcblQlez4AjO5hgDFaa7phYt7716YWisY3RjAaQPlxgv+G3GltHHDJIfzEC5aRxdf62B9zMg==", + "version": "3.957.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.957.0.tgz", + "integrity": "sha512-EqFfOkNZt4oJdyxFoP+PxO4JoEnAnTNOiwLKr57F0Hi+Qp5WYPJHdMFtHrzw6j2+atXQIfQUvtk1q6eQbcvMTw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-user-agent": "3.954.0", - "@aws-sdk/types": "3.953.0", - "@smithy/node-config-provider": "^4.3.6", - "@smithy/types": "^4.10.0", "tslib": "^2.6.2" }, "engines": { "node": ">=18.0.0" }, "peerDependencies": { - "aws-crt": ">=1.0.0" - }, - "peerDependenciesMeta": { - "aws-crt": { - "optional": true - } + "@aws-sdk/client-dynamodb": "^3.957.0" } }, "node_modules/@napi-rs/wasm-runtime": { @@ -3493,9 +3037,9 @@ } }, "node_modules/@sinclair/typebox": { - "version": "0.34.41", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz", - "integrity": "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==", + "version": "0.34.43", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.43.tgz", + "integrity": "sha512-zD2/pAP6nq+ypyNPxsDhc5as3BamstGwCvhOEFTvull2qog9fdb/sj4m/431mk6iuXXW+WE1PER94uBDqxkoIg==", "dev": true, "license": "MIT" }, @@ -3712,6 +3256,20 @@ "node": ">=18.0.0" } }, + "node_modules/@smithy/md5-js": { + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.2.7.tgz", + "integrity": "sha512-Wv6JcUxtOLTnxvNjDnAiATUsk8gvA6EeS8zzHig07dotpByYsLot+m0AaQEniUBjx97AC41MQR4hW0baraD1Xw==", + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.11.0", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/@smithy/middleware-content-length": { "version": "4.2.7", "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.7.tgz", @@ -4362,17 +3920,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.50.0.tgz", - "integrity": "sha512-O7QnmOXYKVtPrfYzMolrCTfkezCJS9+ljLdKW/+DCvRsc3UAz+sbH6Xcsv7p30+0OwUbeWfUDAQE0vpabZ3QLg==", + "version": "8.50.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.50.1.tgz", + "integrity": "sha512-PKhLGDq3JAg0Jk/aK890knnqduuI/Qj+udH7wCf0217IGi4gt+acgCyPVe79qoT+qKUvHMDQkwJeKW9fwl8Cyw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.50.0", - "@typescript-eslint/type-utils": "8.50.0", - "@typescript-eslint/utils": "8.50.0", - "@typescript-eslint/visitor-keys": "8.50.0", + "@typescript-eslint/scope-manager": "8.50.1", + "@typescript-eslint/type-utils": "8.50.1", + "@typescript-eslint/utils": "8.50.1", + "@typescript-eslint/visitor-keys": "8.50.1", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" @@ -4385,23 +3943,23 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.50.0", + "@typescript-eslint/parser": "^8.50.1", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.50.0.tgz", - "integrity": "sha512-6/cmF2piao+f6wSxUsJLZjck7OQsYyRtcOZS02k7XINSNlz93v6emM8WutDQSXnroG2xwYlEVHJI+cPA7CPM3Q==", + "version": "8.50.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.50.1.tgz", + "integrity": "sha512-hM5faZwg7aVNa819m/5r7D0h0c9yC4DUlWAOvHAtISdFTc8xB86VmX5Xqabrama3wIPJ/q9RbGS1worb6JfnMg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.50.0", - "@typescript-eslint/types": "8.50.0", - "@typescript-eslint/typescript-estree": "8.50.0", - "@typescript-eslint/visitor-keys": "8.50.0", + "@typescript-eslint/scope-manager": "8.50.1", + "@typescript-eslint/types": "8.50.1", + "@typescript-eslint/typescript-estree": "8.50.1", + "@typescript-eslint/visitor-keys": "8.50.1", "debug": "^4.3.4" }, "engines": { @@ -4417,14 +3975,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.50.0.tgz", - "integrity": "sha512-Cg/nQcL1BcoTijEWyx4mkVC56r8dj44bFDvBdygifuS20f3OZCHmFbjF34DPSi07kwlFvqfv/xOLnJ5DquxSGQ==", + "version": "8.50.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.50.1.tgz", + "integrity": "sha512-E1ur1MCVf+YiP89+o4Les/oBAVzmSbeRB0MQLfSlYtbWU17HPxZ6Bhs5iYmKZRALvEuBoXIZMOIRRc/P++Ortg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.50.0", - "@typescript-eslint/types": "^8.50.0", + "@typescript-eslint/tsconfig-utils": "^8.50.1", + "@typescript-eslint/types": "^8.50.1", "debug": "^4.3.4" }, "engines": { @@ -4439,14 +3997,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.50.0.tgz", - "integrity": "sha512-xCwfuCZjhIqy7+HKxBLrDVT5q/iq7XBVBXLn57RTIIpelLtEIZHXAF/Upa3+gaCpeV1NNS5Z9A+ID6jn50VD4A==", + "version": "8.50.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.50.1.tgz", + "integrity": "sha512-mfRx06Myt3T4vuoHaKi8ZWNTPdzKPNBhiblze5N50//TSHOAQQevl/aolqA/BcqqbJ88GUnLqjjcBc8EWdBcVw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.50.0", - "@typescript-eslint/visitor-keys": "8.50.0" + "@typescript-eslint/types": "8.50.1", + "@typescript-eslint/visitor-keys": "8.50.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4457,9 +4015,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.50.0.tgz", - "integrity": "sha512-vxd3G/ybKTSlm31MOA96gqvrRGv9RJ7LGtZCn2Vrc5htA0zCDvcMqUkifcjrWNNKXHUU3WCkYOzzVSFBd0wa2w==", + "version": "8.50.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.50.1.tgz", + "integrity": "sha512-ooHmotT/lCWLXi55G4mvaUF60aJa012QzvLK0Y+Mp4WdSt17QhMhWOaBWeGTFVkb2gDgBe19Cxy1elPXylslDw==", "dev": true, "license": "MIT", "engines": { @@ -4474,15 +4032,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.50.0.tgz", - "integrity": "sha512-7OciHT2lKCewR0mFoBrvZJ4AXTMe/sYOe87289WAViOocEmDjjv8MvIOT2XESuKj9jp8u3SZYUSh89QA4S1kQw==", + "version": "8.50.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.50.1.tgz", + "integrity": "sha512-7J3bf022QZE42tYMO6SL+6lTPKFk/WphhRPe9Tw/el+cEwzLz1Jjz2PX3GtGQVxooLDKeMVmMt7fWpYRdG5Etg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.50.0", - "@typescript-eslint/typescript-estree": "8.50.0", - "@typescript-eslint/utils": "8.50.0", + "@typescript-eslint/types": "8.50.1", + "@typescript-eslint/typescript-estree": "8.50.1", + "@typescript-eslint/utils": "8.50.1", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -4499,9 +4057,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.50.0.tgz", - "integrity": "sha512-iX1mgmGrXdANhhITbpp2QQM2fGehBse9LbTf0sidWK6yg/NE+uhV5dfU1g6EYPlcReYmkE9QLPq/2irKAmtS9w==", + "version": "8.50.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.50.1.tgz", + "integrity": "sha512-v5lFIS2feTkNyMhd7AucE/9j/4V9v5iIbpVRncjk/K0sQ6Sb+Np9fgYS/63n6nwqahHQvbmujeBL7mp07Q9mlA==", "dev": true, "license": "MIT", "engines": { @@ -4513,16 +4071,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.50.0.tgz", - "integrity": "sha512-W7SVAGBR/IX7zm1t70Yujpbk+zdPq/u4soeFSknWFdXIFuWsBGBOUu/Tn/I6KHSKvSh91OiMuaSnYp3mtPt5IQ==", + "version": "8.50.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.50.1.tgz", + "integrity": "sha512-woHPdW+0gj53aM+cxchymJCrh0cyS7BTIdcDxWUNsclr9VDkOSbqC13juHzxOmQ22dDkMZEpZB+3X1WpUvzgVQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.50.0", - "@typescript-eslint/tsconfig-utils": "8.50.0", - "@typescript-eslint/types": "8.50.0", - "@typescript-eslint/visitor-keys": "8.50.0", + "@typescript-eslint/project-service": "8.50.1", + "@typescript-eslint/tsconfig-utils": "8.50.1", + "@typescript-eslint/types": "8.50.1", + "@typescript-eslint/visitor-keys": "8.50.1", "debug": "^4.3.4", "minimatch": "^9.0.4", "semver": "^7.6.0", @@ -4541,16 +4099,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.50.0.tgz", - "integrity": "sha512-87KgUXET09CRjGCi2Ejxy3PULXna63/bMYv72tCAlDJC3Yqwln0HiFJ3VJMst2+mEtNtZu5oFvX4qJGjKsnAgg==", + "version": "8.50.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.50.1.tgz", + "integrity": "sha512-lCLp8H1T9T7gPbEuJSnHwnSuO9mDf8mfK/Nion5mZmiEaQD9sWf9W4dfeFqRyqRjF06/kBuTmAqcs9sewM2NbQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.50.0", - "@typescript-eslint/types": "8.50.0", - "@typescript-eslint/typescript-estree": "8.50.0" + "@typescript-eslint/scope-manager": "8.50.1", + "@typescript-eslint/types": "8.50.1", + "@typescript-eslint/typescript-estree": "8.50.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4565,13 +4123,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.50.0.tgz", - "integrity": "sha512-Xzmnb58+Db78gT/CCj/PVCvK+zxbnsw6F+O1oheYszJbBSdEjVhQi3C/Xttzxgi/GLmpvOggRs1RFpiJ8+c34Q==", + "version": "8.50.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.50.1.tgz", + "integrity": "sha512-IrDKrw7pCRUR94zeuCSUWQ+w8JEf5ZX5jl/e6AHGSLi1/zIr0lgutfn/7JpfCey+urpgQEdrZVYzCaVVKiTwhQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.50.0", + "@typescript-eslint/types": "8.50.1", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -5114,9 +4672,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.9.8", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.8.tgz", - "integrity": "sha512-Y1fOuNDowLfgKOypdc9SPABfoWXuZHBOyCS4cD52IeZBhr4Md6CLLs6atcxVrzRmQ06E7hSlm5bHHApPKR/byA==", + "version": "2.9.11", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.11.tgz", + "integrity": "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -5238,9 +4796,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001760", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001760.tgz", - "integrity": "sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==", + "version": "1.0.30001761", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001761.tgz", + "integrity": "sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g==", "dev": true, "funding": [ { @@ -5479,9 +5037,9 @@ } }, "node_modules/dedent": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", - "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.1.tgz", + "integrity": "sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==", "dev": true, "license": "MIT", "peerDependencies": { @@ -8646,16 +8204,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.50.0.tgz", - "integrity": "sha512-Q1/6yNUmCpH94fbgMUMg2/BSAr/6U7GBk61kZTv1/asghQOWOjTlp9K8mixS5NcJmm2creY+UFfGeW/+OcA64A==", + "version": "8.50.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.50.1.tgz", + "integrity": "sha512-ytTHO+SoYSbhAH9CrYnMhiLx8To6PSSvqnvXyPUgPETCvB6eBKmTI9w6XMPS3HsBRGkwTVBX+urA8dYQx6bHfQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.50.0", - "@typescript-eslint/parser": "8.50.0", - "@typescript-eslint/typescript-estree": "8.50.0", - "@typescript-eslint/utils": "8.50.0" + "@typescript-eslint/eslint-plugin": "8.50.1", + "@typescript-eslint/parser": "8.50.1", + "@typescript-eslint/typescript-estree": "8.50.1", + "@typescript-eslint/utils": "8.50.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -8726,9 +8284,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.2.tgz", - "integrity": "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { diff --git a/package.json b/package.json index 037eb2c..a3c7553 100644 --- a/package.json +++ b/package.json @@ -39,8 +39,8 @@ "@types/aws-lambda": "8.10.159", "@types/jest": "30.0.0", "@types/node": "25.0.3", - "@typescript-eslint/eslint-plugin": "8.50.0", - "@typescript-eslint/parser": "8.50.0", + "@typescript-eslint/eslint-plugin": "8.50.1", + "@typescript-eslint/parser": "8.50.1", "eslint": "9.39.2", "eslint-config-prettier": "10.1.8", "globals": "16.5.0", @@ -51,14 +51,14 @@ "ts-jest": "29.4.6", "ts-node": "10.9.2", "typescript": "5.9.3", - "typescript-eslint": "8.50.0" + "typescript-eslint": "8.50.1" }, "dependencies": { - "@aws-sdk/client-dynamodb": "3.956.0", - "@aws-sdk/client-lambda": "3.956.0", - "@aws-sdk/client-sns": "3.956.0", - "@aws-sdk/lib-dynamodb": "3.956.0", - "@leanstacks/lambda-utils": "0.3.0-alpha.4", + "@aws-sdk/client-dynamodb": "3.958.0", + "@aws-sdk/client-lambda": "3.958.0", + "@aws-sdk/client-sns": "3.958.0", + "@aws-sdk/lib-dynamodb": "3.958.0", + "@leanstacks/lambda-utils": "0.4.0-alpha.1", "zod": "4.2.1" } } From d5296d50cf947463cfccc05e1e97e6da4065de75 Mon Sep 17 00:00:00 2001 From: Matthew Warman Date: Wed, 24 Dec 2025 06:39:19 -0500 Subject: [PATCH 6/9] feat: add SNS stack for task event messaging and update configuration --- docs/ConfigurationGuide.md | 19 ++-- docs/InfrastructureGuide.md | 32 ++++++ infrastructure/app.ts | 11 ++ infrastructure/stacks/lambda-stack.test.ts | 4 + infrastructure/stacks/lambda-stack.ts | 10 ++ infrastructure/stacks/sns-stack.test.ts | 114 +++++++++++++++++++++ infrastructure/stacks/sns-stack.ts | 46 +++++++++ src/utils/config.test.ts | 53 ++++++++++ src/utils/config.ts | 1 + 9 files changed, 282 insertions(+), 8 deletions(-) create mode 100644 infrastructure/stacks/sns-stack.test.ts create mode 100644 infrastructure/stacks/sns-stack.ts diff --git a/docs/ConfigurationGuide.md b/docs/ConfigurationGuide.md index 2a2cd1d..ba756f0 100644 --- a/docs/ConfigurationGuide.md +++ b/docs/ConfigurationGuide.md @@ -10,14 +10,15 @@ The application configuration is managed through environment variables. These va The following environment variables are available for configuring the application: -| Variable | Type | Description | Default | Required | -| ------------------- | ------- | ------------------------------------------------ | ----------- | -------- | -| `TASKS_TABLE` | string | The name of the DynamoDB table for storing tasks | - | Yes | -| `AWS_REGION` | string | The AWS region where resources are deployed | `us-east-1` | No | -| `LOGGING_ENABLED` | boolean | Enable or disable application logging | `true` | No | -| `LOGGING_LEVEL` | enum | Logging level: `debug`, `info`, `warn`, `error` | `debug` | No | -| `LOGGING_FORMAT` | enum | Logging format: `text`, `json` | `json` | No | -| `CORS_ALLOW_ORIGIN` | string | CORS allow origin header value | `*` | No | +| Variable | Type | Description | Default | Required | +| ---------------------- | ------- | ------------------------------------------------ | ----------- | -------- | +| `TASKS_TABLE` | string | The name of the DynamoDB table for storing tasks | - | Yes | +| `TASK_EVENT_TOPIC_ARN` | string | The ARN of the SNS topic for task events | - | Yes | +| `AWS_REGION` | string | The AWS region where resources are deployed | `us-east-1` | No | +| `LOGGING_ENABLED` | boolean | Enable or disable application logging | `true` | No | +| `LOGGING_LEVEL` | enum | Logging level: `debug`, `info`, `warn`, `error` | `debug` | No | +| `LOGGING_FORMAT` | enum | Logging format: `text`, `json` | `json` | No | +| `CORS_ALLOW_ORIGIN` | string | CORS allow origin header value | `*` | No | ### Usage @@ -27,6 +28,7 @@ Application configuration is accessed through the `config` object exported from import { config } from './utils/config'; console.log(`Tasks table: ${config.TASKS_TABLE}`); +console.log(`Task event topic ARN: ${config.TASK_EVENT_TOPIC_ARN}`); console.log(`Logging enabled: ${config.LOGGING_ENABLED}`); ``` @@ -155,6 +157,7 @@ Infrastructure configuration variables are passed to Lambda functions with modif | `CDK_APP_LOGGING_FORMAT` | `LOGGING_FORMAT` | | `CDK_CORS_ALLOW_ORIGIN` | `CORS_ALLOW_ORIGIN` | | (DynamoDB table name) | `TASKS_TABLE` | +| (SNS topic ARN) | `TASK_EVENT_TOPIC_ARN` | | (AWS Region) | `AWS_REGION` | --- diff --git a/docs/InfrastructureGuide.md b/docs/InfrastructureGuide.md index 0a9c808..3bc8aeb 100644 --- a/docs/InfrastructureGuide.md +++ b/docs/InfrastructureGuide.md @@ -11,6 +11,7 @@ The infrastructure is organized into two main AWS CDK stacks: | Stack Name Pattern | Purpose | | ------------------------- | ------------------------------------------ | | `{app-name}-data-{env}` | Manages DynamoDB tables and data resources | +| `{app-name}-sns-{env}` | Manages SNS topics for messaging | | `{app-name}-lambda-{env}` | Manages Lambda functions and API Gateway | --- @@ -34,6 +35,24 @@ The infrastructure is organized into two main AWS CDK stacks: --- +## SNS Stack + +**Purpose:** Manages SNS topics for messaging and event publishing. + +**Key Resources:** + +| Resource | Name Pattern | Key Properties | +| --------- | ----------------------------- | ------------------------------------------------- | +| SNS Topic | `{app-name}-task-event-{env}` | Standard (non-FIFO) topic, AWS-managed encryption | + +**Outputs:** + +| Output Name | Export Name Pattern | Description | +| ------------------- | --------------------------------------- | ------------------------------- | +| `TaskEventTopicArn` | `{app-name}-task-event-topic-arn-{env}` | Task Event Topic ARN (exported) | + +--- + ## Lambda Stack **Purpose:** Manages Lambda functions, API Gateway, and application runtime resources. @@ -49,6 +68,19 @@ The infrastructure is organized into two main AWS CDK stacks: | Lambda Function | `{app-name}-delete-task-{env}` | Delete a task (DynamoDB DeleteItem) | | API Gateway | `{app-name}-api-{env}` | REST API for Lambda functions | +**Environment Variables Passed to Lambda Functions:** + +All Lambda functions receive the following environment variables from the CDK configuration: + +| Variable | Source | Purpose | +| ---------------------- | ------------------------- | ---------------------------------------- | +| `TASKS_TABLE` | Data Stack output | DynamoDB table name for tasks | +| `TASK_EVENT_TOPIC_ARN` | SNS Stack output | SNS topic ARN for publishing task events | +| `LOGGING_ENABLED` | `CDK_APP_LOGGING_ENABLED` | Enable/disable application logging | +| `LOGGING_LEVEL` | `CDK_APP_LOGGING_LEVEL` | Application logging level | +| `LOGGING_FORMAT` | `CDK_APP_LOGGING_FORMAT` | Application logging format | +| `CORS_ALLOW_ORIGIN` | `CDK_CORS_ALLOW_ORIGIN` | CORS allow origin header value | + **Outputs:** | Output Name | Export Name Pattern | Description | diff --git a/infrastructure/app.ts b/infrastructure/app.ts index c2f5e2d..f25d8d7 100644 --- a/infrastructure/app.ts +++ b/infrastructure/app.ts @@ -4,6 +4,7 @@ import * as cdk from 'aws-cdk-lib'; import { getConfig, getEnvironmentConfig, getTags } from './utils/config'; import { DataStack } from './stacks/data-stack'; +import { SnsStack } from './stacks/sns-stack'; import { LambdaStack } from './stacks/lambda-stack'; // Load and validate configuration @@ -27,6 +28,15 @@ const dataStack = new DataStack(app, `${config.CDK_APP_NAME}-data-stack-${config ...(environmentConfig && { env: environmentConfig }), }); +// Create SNS Stack +const snsStack = new SnsStack(app, `${config.CDK_APP_NAME}-sns-stack-${config.CDK_ENV}`, { + appName: config.CDK_APP_NAME, + envName: config.CDK_ENV, + stackName: `${config.CDK_APP_NAME}-sns-${config.CDK_ENV}`, + description: `SNS resources for ${config.CDK_APP_NAME} (${config.CDK_ENV})`, + ...(environmentConfig && { env: environmentConfig }), +}); + // Create Lambda Stack new LambdaStack(app, `${config.CDK_APP_NAME}-lambda-stack-${config.CDK_ENV}`, { appName: config.CDK_APP_NAME, @@ -34,6 +44,7 @@ new LambdaStack(app, `${config.CDK_APP_NAME}-lambda-stack-${config.CDK_ENV}`, { stackName: `${config.CDK_APP_NAME}-lambda-${config.CDK_ENV}`, description: `Lambda functions and API Gateway for ${config.CDK_APP_NAME} (${config.CDK_ENV})`, taskTable: dataStack.taskTable, + taskEventTopicArn: snsStack.taskEventTopic.topicArn, loggingEnabled: config.CDK_APP_LOGGING_ENABLED, loggingLevel: config.CDK_APP_LOGGING_LEVEL, loggingFormat: config.CDK_APP_LOGGING_FORMAT, diff --git a/infrastructure/stacks/lambda-stack.test.ts b/infrastructure/stacks/lambda-stack.test.ts index 8cb8e00..44e8ed8 100644 --- a/infrastructure/stacks/lambda-stack.test.ts +++ b/infrastructure/stacks/lambda-stack.test.ts @@ -40,6 +40,7 @@ describe('LambdaStack', () => { appName: 'lambda-starter', envName: 'dev', taskTable: testMockTable, + taskEventTopicArn: 'arn:aws:sns:us-east-1:123456789012:lambda-starter-task-event-dev', loggingEnabled: true, loggingLevel: 'debug', loggingFormat: 'json', @@ -103,6 +104,7 @@ describe('LambdaStack', () => { Environment: { Variables: { TASKS_TABLE: Match.anyValue(), + TASK_EVENT_TOPIC_ARN: 'arn:aws:sns:us-east-1:123456789012:lambda-starter-task-event-dev', LOGGING_ENABLED: 'true', LOGGING_LEVEL: 'debug', LOGGING_FORMAT: 'json', @@ -316,6 +318,7 @@ describe('LambdaStack', () => { appName: 'lambda-starter', envName: 'prd', taskTable: testMockTable, + taskEventTopicArn: 'arn:aws:sns:us-east-1:123456789012:lambda-starter-task-event-prd', loggingEnabled: true, loggingLevel: 'info', loggingFormat: 'json', @@ -372,6 +375,7 @@ describe('LambdaStack', () => { appName: 'lambda-starter', envName: 'dev', taskTable: testMockTable, + taskEventTopicArn: 'arn:aws:sns:us-east-1:123456789012:lambda-starter-task-event-dev', loggingEnabled: true, loggingLevel: 'debug', loggingFormat: 'json', diff --git a/infrastructure/stacks/lambda-stack.ts b/infrastructure/stacks/lambda-stack.ts index 69346a0..0952c58 100644 --- a/infrastructure/stacks/lambda-stack.ts +++ b/infrastructure/stacks/lambda-stack.ts @@ -26,6 +26,11 @@ export interface LambdaStackProps extends cdk.StackProps { */ taskTable: dynamodb.ITable; + /** + * ARN of the Task Event SNS topic. + */ + taskEventTopicArn: string; + /** * Whether to enable application logging. */ @@ -92,6 +97,7 @@ export class LambdaStack extends cdk.Stack { entry: path.join(__dirname, '../../src/handlers/list-tasks.ts'), environment: { TASKS_TABLE: props.taskTable.tableName, + TASK_EVENT_TOPIC_ARN: props.taskEventTopicArn, LOGGING_ENABLED: props.loggingEnabled.toString(), LOGGING_LEVEL: props.loggingLevel, LOGGING_FORMAT: props.loggingFormat, @@ -124,6 +130,7 @@ export class LambdaStack extends cdk.Stack { entry: path.join(__dirname, '../../src/handlers/get-task.ts'), environment: { TASKS_TABLE: props.taskTable.tableName, + TASK_EVENT_TOPIC_ARN: props.taskEventTopicArn, LOGGING_ENABLED: props.loggingEnabled.toString(), LOGGING_LEVEL: props.loggingLevel, LOGGING_FORMAT: props.loggingFormat, @@ -156,6 +163,7 @@ export class LambdaStack extends cdk.Stack { entry: path.join(__dirname, '../../src/handlers/create-task.ts'), environment: { TASKS_TABLE: props.taskTable.tableName, + TASK_EVENT_TOPIC_ARN: props.taskEventTopicArn, LOGGING_ENABLED: props.loggingEnabled.toString(), LOGGING_LEVEL: props.loggingLevel, LOGGING_FORMAT: props.loggingFormat, @@ -188,6 +196,7 @@ export class LambdaStack extends cdk.Stack { entry: path.join(__dirname, '../../src/handlers/update-task.ts'), environment: { TASKS_TABLE: props.taskTable.tableName, + TASK_EVENT_TOPIC_ARN: props.taskEventTopicArn, LOGGING_ENABLED: props.loggingEnabled.toString(), LOGGING_LEVEL: props.loggingLevel, LOGGING_FORMAT: props.loggingFormat, @@ -220,6 +229,7 @@ export class LambdaStack extends cdk.Stack { entry: path.join(__dirname, '../../src/handlers/delete-task.ts'), environment: { TASKS_TABLE: props.taskTable.tableName, + TASK_EVENT_TOPIC_ARN: props.taskEventTopicArn, LOGGING_ENABLED: props.loggingEnabled.toString(), LOGGING_LEVEL: props.loggingLevel, LOGGING_FORMAT: props.loggingFormat, diff --git a/infrastructure/stacks/sns-stack.test.ts b/infrastructure/stacks/sns-stack.test.ts new file mode 100644 index 0000000..648341c --- /dev/null +++ b/infrastructure/stacks/sns-stack.test.ts @@ -0,0 +1,114 @@ +import * as cdk from 'aws-cdk-lib'; +import * as sns from 'aws-cdk-lib/aws-sns'; +import { Template } from 'aws-cdk-lib/assertions'; +import { SnsStack } from './sns-stack'; + +describe('SnsStack', () => { + let stack: SnsStack; + let template: Template; + + beforeEach(() => { + // Create a test CDK app + const app = new cdk.App(); + + // Instantiate the SnsStack + stack = new SnsStack(app, 'TestSnsStack', { + appName: 'test-app', + envName: 'test', + }); + + // Create a template from the stack for assertions + template = Template.fromStack(stack); + }); + + describe('SNS Topic', () => { + it('should create a SNS topic with correct properties', () => { + // Assert - verify SNS topic exists with correct properties + template.hasResourceProperties('AWS::SNS::Topic', { + TopicName: 'test-app-task-event-test', + DisplayName: 'Task Event Topic (test)', + }); + }); + + it('should expose the task event topic', () => { + // Assert + expect(stack.taskEventTopic).toBeDefined(); + expect(stack.taskEventTopic).toBeInstanceOf(sns.Topic); + }); + + it('should create topic with encryption enabled by default', () => { + // Assert - SNS topics have AWS-managed encryption by default + template.resourceCountIs('AWS::SNS::Topic', 1); + }); + }); + + describe('Stack Outputs', () => { + it('should export TaskEventTopicArn output', () => { + // Assert - verify the output exists + template.hasOutput('TaskEventTopicArn', { + Export: { + Name: 'test-app-task-event-topic-arn-test', + }, + }); + }); + + it('should output the correct topic ARN', () => { + // Assert - verify the topic ARN is exported + const output = stack.node.findChild('TaskEventTopicArn'); + expect(output).toBeDefined(); + }); + }); + + describe('Stack Configuration', () => { + it('should set topic name with correct naming convention', () => { + // Assert + template.hasResourceProperties('AWS::SNS::Topic', { + TopicName: 'test-app-task-event-test', + }); + }); + + it('should create stack with dev environment naming', () => { + // Arrange + const app = new cdk.App(); + const devStack = new SnsStack(app, 'DevSnsStack', { + appName: 'lambda-starter', + envName: 'dev', + }); + + const devTemplate = Template.fromStack(devStack); + + // Assert + devTemplate.hasResourceProperties('AWS::SNS::Topic', { + TopicName: 'lambda-starter-task-event-dev', + }); + }); + + it('should create stack with prod environment naming', () => { + // Arrange + const app = new cdk.App(); + const prodStack = new SnsStack(app, 'ProdSnsStack', { + appName: 'lambda-starter', + envName: 'prd', + }); + + const prodTemplate = Template.fromStack(prodStack); + + // Assert + prodTemplate.hasResourceProperties('AWS::SNS::Topic', { + TopicName: 'lambda-starter-task-event-prd', + }); + }); + }); + + describe('Topic Properties', () => { + it('should create standard (non-FIFO) SNS topic', () => { + // Assert - topic should not have FIFO properties + template.allResources('AWS::SNS::Topic', (resource: any) => { + // FIFO topic would have FifoTopic: true + if (resource.properties.FifoTopic) { + throw new Error('Topic should not be FIFO'); + } + }); + }); + }); +}); diff --git a/infrastructure/stacks/sns-stack.ts b/infrastructure/stacks/sns-stack.ts new file mode 100644 index 0000000..00c0c4e --- /dev/null +++ b/infrastructure/stacks/sns-stack.ts @@ -0,0 +1,46 @@ +import * as cdk from 'aws-cdk-lib'; +import * as sns from 'aws-cdk-lib/aws-sns'; +import { Construct } from 'constructs'; + +/** + * Properties for the SnsStack. + */ +export interface SnsStackProps extends cdk.StackProps { + /** + * Application name. + */ + appName: string; + + /** + * Environment name (dev, qat, prd). + */ + envName: string; +} + +/** + * CDK Stack for SNS topics and messaging resources. + */ +export class SnsStack extends cdk.Stack { + /** + * The Task Event SNS topic. + */ + public readonly taskEventTopic: sns.ITopic; + + constructor(scope: Construct, id: string, props: SnsStackProps) { + super(scope, id, props); + + // Create Task Event Topic + this.taskEventTopic = new sns.Topic(this, 'TaskEventTopic', { + topicName: `${props.appName}-task-event-${props.envName}`, + displayName: `Task Event Topic (${props.envName})`, + fifo: false, + }); + + // Output the topic ARN + new cdk.CfnOutput(this, 'TaskEventTopicArn', { + value: this.taskEventTopic.topicArn, + description: 'The ARN of the Task Event SNS topic', + exportName: `${props.appName}-task-event-topic-arn-${props.envName}`, + }); + } +} diff --git a/src/utils/config.test.ts b/src/utils/config.test.ts index f041c71..afb5699 100644 --- a/src/utils/config.test.ts +++ b/src/utils/config.test.ts @@ -19,6 +19,7 @@ describe('config', () => { it('should validate and return config with required environment variables', () => { // Arrange process.env.TASKS_TABLE = 'my-tasks-table'; + process.env.TASK_EVENT_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:my-topic'; // Act const { config } = require('./config'); @@ -26,11 +27,13 @@ describe('config', () => { // Assert expect(config).toBeDefined(); expect(config.TASKS_TABLE).toBe('my-tasks-table'); + expect(config.TASK_EVENT_TOPIC_ARN).toBe('arn:aws:sns:us-east-1:123456789012:my-topic'); }); it('should apply default values for optional environment variables', () => { // Arrange process.env.TASKS_TABLE = 'my-tasks-table'; + process.env.TASK_EVENT_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:my-topic'; // Act const { config } = require('./config'); @@ -46,6 +49,7 @@ describe('config', () => { it('should use provided values instead of defaults', () => { // Arrange process.env.TASKS_TABLE = 'my-tasks-table'; + process.env.TASK_EVENT_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:my-topic'; process.env.AWS_REGION = 'us-west-2'; process.env.LOGGING_ENABLED = 'false'; process.env.LOGGING_LEVEL = 'error'; @@ -66,6 +70,7 @@ describe('config', () => { it('should throw error when required TASKS_TABLE is missing', () => { // Arrange delete process.env.TASKS_TABLE; + process.env.TASK_EVENT_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:my-topic'; // Act & Assert expect(() => { @@ -77,6 +82,31 @@ describe('config', () => { it('should throw error when TASKS_TABLE is empty string', () => { // Arrange process.env.TASKS_TABLE = ''; + process.env.TASK_EVENT_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:my-topic'; + + // Act & Assert + expect(() => { + const { config: testConfig } = require('./config'); + return testConfig; + }).toThrow(); + }); + + it('should throw error when required TASK_EVENT_TOPIC_ARN is missing', () => { + // Arrange + process.env.TASKS_TABLE = 'my-tasks-table'; + delete process.env.TASK_EVENT_TOPIC_ARN; + + // Act & Assert + expect(() => { + const { config: testConfig } = require('./config'); + return testConfig; + }).toThrow(); + }); + + it('should throw error when TASK_EVENT_TOPIC_ARN is empty string', () => { + // Arrange + process.env.TASKS_TABLE = 'my-tasks-table'; + process.env.TASK_EVENT_TOPIC_ARN = ''; // Act & Assert expect(() => { @@ -88,6 +118,7 @@ describe('config', () => { it('should transform LOGGING_ENABLED string to boolean true', () => { // Arrange process.env.TASKS_TABLE = 'my-tasks-table'; + process.env.TASK_EVENT_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:my-topic'; process.env.LOGGING_ENABLED = 'true'; // Act @@ -101,6 +132,7 @@ describe('config', () => { it('should transform LOGGING_ENABLED string to boolean false', () => { // Arrange process.env.TASKS_TABLE = 'my-tasks-table'; + process.env.TASK_EVENT_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:my-topic'; process.env.LOGGING_ENABLED = 'false'; // Act @@ -114,12 +146,14 @@ describe('config', () => { it('should validate LOGGING_LEVEL enum values', () => { // Arrange process.env.TASKS_TABLE = 'my-tasks-table'; + process.env.TASK_EVENT_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:my-topic'; // Act & Assert - valid values const validLogLevels = ['debug', 'info', 'warn', 'error']; validLogLevels.forEach((level) => { jest.resetModules(); process.env.TASKS_TABLE = 'my-tasks-table'; + process.env.TASK_EVENT_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:my-topic'; process.env.LOGGING_LEVEL = level; const { config } = require('./config'); expect(config.LOGGING_LEVEL).toBe(level); @@ -129,6 +163,7 @@ describe('config', () => { it('should throw error for invalid LOGGING_LEVEL', () => { // Arrange process.env.TASKS_TABLE = 'my-tasks-table'; + process.env.TASK_EVENT_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:my-topic'; process.env.LOGGING_LEVEL = 'invalid'; // Act & Assert @@ -141,6 +176,7 @@ describe('config', () => { it('should throw error for invalid LOGGING_ENABLED value', () => { // Arrange process.env.TASKS_TABLE = 'my-tasks-table'; + process.env.TASK_EVENT_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:my-topic'; process.env.LOGGING_ENABLED = 'yes'; // Act & Assert @@ -153,12 +189,14 @@ describe('config', () => { it('should validate LOGGING_FORMAT enum values', () => { // Arrange process.env.TASKS_TABLE = 'my-tasks-table'; + process.env.TASK_EVENT_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:my-topic'; // Act & Assert - valid values const validLogFormats = ['text', 'json']; validLogFormats.forEach((format) => { jest.resetModules(); process.env.TASKS_TABLE = 'my-tasks-table'; + process.env.TASK_EVENT_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:my-topic'; process.env.LOGGING_FORMAT = format; const { config } = require('./config'); expect(config.LOGGING_FORMAT).toBe(format); @@ -168,6 +206,7 @@ describe('config', () => { it('should throw error for invalid LOGGING_FORMAT', () => { // Arrange process.env.TASKS_TABLE = 'my-tasks-table'; + process.env.TASK_EVENT_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:my-topic'; process.env.LOGGING_FORMAT = 'xml'; // Act & Assert @@ -182,38 +221,46 @@ describe('config', () => { it('should refresh config when environment variables change', () => { // Arrange process.env.TASKS_TABLE = 'original-table'; + process.env.TASK_EVENT_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:original-topic'; process.env.AWS_REGION = 'us-east-1'; const { config, refresh } = require('./config'); expect(config.TASKS_TABLE).toBe('original-table'); + expect(config.TASK_EVENT_TOPIC_ARN).toBe('arn:aws:sns:us-east-1:123456789012:original-topic'); expect(config.AWS_REGION).toBe('us-east-1'); // Act - change environment and refresh process.env.TASKS_TABLE = 'updated-table'; + process.env.TASK_EVENT_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:updated-topic'; process.env.AWS_REGION = 'eu-west-1'; const refreshedConfig = refresh(); // Assert expect(refreshedConfig.TASKS_TABLE).toBe('updated-table'); + expect(refreshedConfig.TASK_EVENT_TOPIC_ARN).toBe('arn:aws:sns:us-east-1:123456789012:updated-topic'); expect(refreshedConfig.AWS_REGION).toBe('eu-west-1'); }); it('should return updated config on refresh', () => { // Arrange process.env.TASKS_TABLE = 'original-table'; + process.env.TASK_EVENT_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:original-topic'; const { refresh } = require('./config'); // Act process.env.TASKS_TABLE = 'new-table'; + process.env.TASK_EVENT_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:new-topic'; const refreshedConfig = refresh(); // Assert expect(refreshedConfig.TASKS_TABLE).toBe('new-table'); + expect(refreshedConfig.TASK_EVENT_TOPIC_ARN).toBe('arn:aws:sns:us-east-1:123456789012:new-topic'); }); it('should throw error on refresh if validation fails', () => { // Arrange process.env.TASKS_TABLE = 'valid-table'; + process.env.TASK_EVENT_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:valid-topic'; const { refresh } = require('./config'); // Act - remove required variable and refresh @@ -228,6 +275,7 @@ describe('config', () => { it('should cache config after first validation', () => { // Arrange process.env.TASKS_TABLE = 'my-tasks-table'; + process.env.TASK_EVENT_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:my-topic'; const configModule = require('./config'); // Act @@ -241,6 +289,7 @@ describe('config', () => { it('should return cached config on subsequent imports', () => { // Arrange process.env.TASKS_TABLE = 'cached-table'; + process.env.TASK_EVENT_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:cached-topic'; process.env.AWS_REGION = 'us-west-1'; // Act @@ -261,6 +310,7 @@ describe('config', () => { it('should provide detailed error message for multiple validation failures', () => { // Arrange delete process.env.TASKS_TABLE; + delete process.env.TASK_EVENT_TOPIC_ARN; process.env.LOGGING_LEVEL = 'invalid'; // Act & Assert @@ -273,6 +323,7 @@ describe('config', () => { it('should include field paths in error messages', () => { // Arrange delete process.env.TASKS_TABLE; + process.env.TASK_EVENT_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:my-topic'; // Act & Assert try { @@ -290,6 +341,7 @@ describe('config', () => { it('should export Config type matching validated schema', () => { // Arrange process.env.TASKS_TABLE = 'my-tasks-table'; + process.env.TASK_EVENT_TOPIC_ARN = 'arn:aws:sns:us-east-1:123456789012:my-topic'; process.env.AWS_REGION = 'us-east-1'; process.env.LOGGING_ENABLED = 'true'; process.env.LOGGING_LEVEL = 'info'; @@ -300,6 +352,7 @@ describe('config', () => { // Assert - verify all expected properties exist and have correct types expect(typeof config.TASKS_TABLE).toBe('string'); + expect(typeof config.TASK_EVENT_TOPIC_ARN).toBe('string'); expect(typeof config.AWS_REGION).toBe('string'); expect(typeof config.LOGGING_ENABLED).toBe('boolean'); expect(['debug', 'info', 'warn', 'error']).toContain(config.LOGGING_LEVEL); diff --git a/src/utils/config.ts b/src/utils/config.ts index 6124b60..c25e288 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -7,6 +7,7 @@ import { createConfigManager } from '@leanstacks/lambda-utils'; const envSchema = z.object({ // Required variables TASKS_TABLE: z.string().min(1, 'TASKS_TABLE environment variable is required'), + TASK_EVENT_TOPIC_ARN: z.string().min(1, 'TASK_EVENT_TOPIC_ARN environment variable is required'), // Optional variables with defaults AWS_REGION: z.string().default('us-east-1'), From a3fc29fb2711838925e9c06a6f04e465ba3fc920 Mon Sep 17 00:00:00 2001 From: Matthew Warman Date: Wed, 24 Dec 2025 07:38:03 -0500 Subject: [PATCH 7/9] feat: update LambdaStack to use SNS topic reference and publish events for task operations --- infrastructure/app.ts | 2 +- infrastructure/stacks/lambda-stack.test.ts | 57 +++- infrastructure/stacks/lambda-stack.ts | 24 +- src/services/task-service.test.ts | 219 +++++++++++---- src/services/task-service.ts | 73 ++++- src/utils/sns-client.test.ts | 301 --------------------- src/utils/sns-client.ts | 62 ----- 7 files changed, 309 insertions(+), 429 deletions(-) delete mode 100644 src/utils/sns-client.test.ts delete mode 100644 src/utils/sns-client.ts diff --git a/infrastructure/app.ts b/infrastructure/app.ts index f25d8d7..4eef96d 100644 --- a/infrastructure/app.ts +++ b/infrastructure/app.ts @@ -44,7 +44,7 @@ new LambdaStack(app, `${config.CDK_APP_NAME}-lambda-stack-${config.CDK_ENV}`, { stackName: `${config.CDK_APP_NAME}-lambda-${config.CDK_ENV}`, description: `Lambda functions and API Gateway for ${config.CDK_APP_NAME} (${config.CDK_ENV})`, taskTable: dataStack.taskTable, - taskEventTopicArn: snsStack.taskEventTopic.topicArn, + taskEventTopic: snsStack.taskEventTopic, loggingEnabled: config.CDK_APP_LOGGING_ENABLED, loggingLevel: config.CDK_APP_LOGGING_LEVEL, loggingFormat: config.CDK_APP_LOGGING_FORMAT, diff --git a/infrastructure/stacks/lambda-stack.test.ts b/infrastructure/stacks/lambda-stack.test.ts index 44e8ed8..dab56c3 100644 --- a/infrastructure/stacks/lambda-stack.test.ts +++ b/infrastructure/stacks/lambda-stack.test.ts @@ -1,6 +1,7 @@ import * as cdk from 'aws-cdk-lib'; import { Match, Template } from 'aws-cdk-lib/assertions'; import * as dynamodb from 'aws-cdk-lib/aws-dynamodb'; +import * as sns from 'aws-cdk-lib/aws-sns'; import { LambdaStack } from './lambda-stack'; // Mock NodejsFunction to avoid Docker bundling during tests @@ -35,12 +36,15 @@ describe('LambdaStack', () => { type: dynamodb.AttributeType.STRING, }, }); + const testMockTopic = new sns.Topic(mockTestStack, 'MockTaskEventTopic', { + topicName: 'mock-task-event-dev', + }); const stack = new LambdaStack(testApp, 'TestLambdaStack', { appName: 'lambda-starter', envName: 'dev', taskTable: testMockTable, - taskEventTopicArn: 'arn:aws:sns:us-east-1:123456789012:lambda-starter-task-event-dev', + taskEventTopic: testMockTopic, loggingEnabled: true, loggingLevel: 'debug', loggingFormat: 'json', @@ -104,7 +108,7 @@ describe('LambdaStack', () => { Environment: { Variables: { TASKS_TABLE: Match.anyValue(), - TASK_EVENT_TOPIC_ARN: 'arn:aws:sns:us-east-1:123456789012:lambda-starter-task-event-dev', + TASK_EVENT_TOPIC_ARN: Match.anyValue(), LOGGING_ENABLED: 'true', LOGGING_LEVEL: 'debug', LOGGING_FORMAT: 'json', @@ -220,6 +224,45 @@ describe('LambdaStack', () => { }); }); + it('should grant Lambda SNS publish permissions for create function', () => { + template.hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: Match.arrayWith([ + Match.objectLike({ + Action: 'sns:Publish', + Resource: Match.anyValue(), + }), + ]), + }, + }); + }); + + it('should grant Lambda SNS publish permissions for update function', () => { + template.hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: Match.arrayWith([ + Match.objectLike({ + Action: 'sns:Publish', + Resource: Match.anyValue(), + }), + ]), + }, + }); + }); + + it('should grant Lambda SNS publish permissions for delete function', () => { + template.hasResourceProperties('AWS::IAM::Policy', { + PolicyDocument: { + Statement: Match.arrayWith([ + Match.objectLike({ + Action: 'sns:Publish', + Resource: Match.anyValue(), + }), + ]), + }, + }); + }); + it('should export API URL', () => { template.hasOutput('ApiUrl', { Export: { @@ -313,12 +356,15 @@ describe('LambdaStack', () => { type: dynamodb.AttributeType.STRING, }, }); + const testMockTopic = new sns.Topic(mockTestStack, 'MockTaskEventTopic', { + topicName: 'mock-task-event-prd', + }); const stack = new LambdaStack(testApp, 'TestLambdaStack', { appName: 'lambda-starter', envName: 'prd', taskTable: testMockTable, - taskEventTopicArn: 'arn:aws:sns:us-east-1:123456789012:lambda-starter-task-event-prd', + taskEventTopic: testMockTopic, loggingEnabled: true, loggingLevel: 'info', loggingFormat: 'json', @@ -370,12 +416,15 @@ describe('LambdaStack', () => { type: dynamodb.AttributeType.STRING, }, }); + const testMockTopic = new sns.Topic(mockTestStack, 'MockTaskEventTopic', { + topicName: 'mock-task-event-dev', + }); const stack = new LambdaStack(testApp, 'TestLambdaStack', { appName: 'lambda-starter', envName: 'dev', taskTable: testMockTable, - taskEventTopicArn: 'arn:aws:sns:us-east-1:123456789012:lambda-starter-task-event-dev', + taskEventTopic: testMockTopic, loggingEnabled: true, loggingLevel: 'debug', loggingFormat: 'json', diff --git a/infrastructure/stacks/lambda-stack.ts b/infrastructure/stacks/lambda-stack.ts index 0952c58..3046231 100644 --- a/infrastructure/stacks/lambda-stack.ts +++ b/infrastructure/stacks/lambda-stack.ts @@ -4,6 +4,7 @@ import * as apigateway from 'aws-cdk-lib/aws-apigateway'; import * as dynamodb from 'aws-cdk-lib/aws-dynamodb'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as logs from 'aws-cdk-lib/aws-logs'; +import * as sns from 'aws-cdk-lib/aws-sns'; import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs'; import { Construct } from 'constructs'; @@ -27,9 +28,9 @@ export interface LambdaStackProps extends cdk.StackProps { taskTable: dynamodb.ITable; /** - * ARN of the Task Event SNS topic. + * Reference to the Task Event SNS topic. */ - taskEventTopicArn: string; + taskEventTopic: sns.ITopic; /** * Whether to enable application logging. @@ -97,7 +98,7 @@ export class LambdaStack extends cdk.Stack { entry: path.join(__dirname, '../../src/handlers/list-tasks.ts'), environment: { TASKS_TABLE: props.taskTable.tableName, - TASK_EVENT_TOPIC_ARN: props.taskEventTopicArn, + TASK_EVENT_TOPIC_ARN: props.taskEventTopic.topicArn, LOGGING_ENABLED: props.loggingEnabled.toString(), LOGGING_LEVEL: props.loggingLevel, LOGGING_FORMAT: props.loggingFormat, @@ -130,7 +131,7 @@ export class LambdaStack extends cdk.Stack { entry: path.join(__dirname, '../../src/handlers/get-task.ts'), environment: { TASKS_TABLE: props.taskTable.tableName, - TASK_EVENT_TOPIC_ARN: props.taskEventTopicArn, + TASK_EVENT_TOPIC_ARN: props.taskEventTopic.topicArn, LOGGING_ENABLED: props.loggingEnabled.toString(), LOGGING_LEVEL: props.loggingLevel, LOGGING_FORMAT: props.loggingFormat, @@ -163,7 +164,7 @@ export class LambdaStack extends cdk.Stack { entry: path.join(__dirname, '../../src/handlers/create-task.ts'), environment: { TASKS_TABLE: props.taskTable.tableName, - TASK_EVENT_TOPIC_ARN: props.taskEventTopicArn, + TASK_EVENT_TOPIC_ARN: props.taskEventTopic.topicArn, LOGGING_ENABLED: props.loggingEnabled.toString(), LOGGING_LEVEL: props.loggingLevel, LOGGING_FORMAT: props.loggingFormat, @@ -188,6 +189,9 @@ export class LambdaStack extends cdk.Stack { // Grant the Lambda function write access to the DynamoDB table props.taskTable.grantWriteData(this.createTaskFunction); + // Grant the Lambda function permission to publish to the SNS topic + props.taskEventTopic.grantPublish(this.createTaskFunction); + // Create the update task Lambda function this.updateTaskFunction = new NodejsFunction(this, 'UpdateTaskFunction', { functionName: `${props.appName}-update-task-${props.envName}`, @@ -196,7 +200,7 @@ export class LambdaStack extends cdk.Stack { entry: path.join(__dirname, '../../src/handlers/update-task.ts'), environment: { TASKS_TABLE: props.taskTable.tableName, - TASK_EVENT_TOPIC_ARN: props.taskEventTopicArn, + TASK_EVENT_TOPIC_ARN: props.taskEventTopic.topicArn, LOGGING_ENABLED: props.loggingEnabled.toString(), LOGGING_LEVEL: props.loggingLevel, LOGGING_FORMAT: props.loggingFormat, @@ -221,6 +225,9 @@ export class LambdaStack extends cdk.Stack { // Grant the Lambda function read and write access to the DynamoDB table props.taskTable.grantReadWriteData(this.updateTaskFunction); + // Grant the Lambda function permission to publish to the SNS topic + props.taskEventTopic.grantPublish(this.updateTaskFunction); + // Create the delete task Lambda function this.deleteTaskFunction = new NodejsFunction(this, 'DeleteTaskFunction', { functionName: `${props.appName}-delete-task-${props.envName}`, @@ -229,7 +236,7 @@ export class LambdaStack extends cdk.Stack { entry: path.join(__dirname, '../../src/handlers/delete-task.ts'), environment: { TASKS_TABLE: props.taskTable.tableName, - TASK_EVENT_TOPIC_ARN: props.taskEventTopicArn, + TASK_EVENT_TOPIC_ARN: props.taskEventTopic.topicArn, LOGGING_ENABLED: props.loggingEnabled.toString(), LOGGING_LEVEL: props.loggingLevel, LOGGING_FORMAT: props.loggingFormat, @@ -254,6 +261,9 @@ export class LambdaStack extends cdk.Stack { // Grant the Lambda function read and write access to the DynamoDB table props.taskTable.grantReadWriteData(this.deleteTaskFunction); + // Grant the Lambda function permission to publish to the SNS topic + props.taskEventTopic.grantPublish(this.deleteTaskFunction); + // Create API Gateway REST API this.api = new apigateway.RestApi(this, 'LambdaStarterApi', { restApiName: `${props.appName}-api-${props.envName}`, diff --git a/src/services/task-service.test.ts b/src/services/task-service.test.ts index 95782e3..bbf1baa 100644 --- a/src/services/task-service.test.ts +++ b/src/services/task-service.test.ts @@ -8,6 +8,7 @@ const mockLoggerDebug = jest.fn(); const mockLoggerInfo = jest.fn(); const mockLoggerError = jest.fn(); const mockRandomUUID = jest.fn(); +const mockPublishToTopic = jest.fn(); jest.mock('crypto', () => ({ randomUUID: mockRandomUUID, @@ -27,9 +28,14 @@ jest.mock('../utils/logger', () => ({ }, })); +jest.mock('@leanstacks/lambda-utils', () => ({ + publishToTopic: mockPublishToTopic, +})); + jest.mock('../utils/config', () => ({ config: { TASKS_TABLE: 'test-tasks-table', + TASK_EVENT_TOPIC_ARN: 'arn:aws:sns:us-east-1:123456789012:test-topic', }, })); @@ -44,6 +50,9 @@ describe('task-service', () => { // Clear all mocks jest.clearAllMocks(); + // Setup publishToTopic mock to return a message ID + mockPublishToTopic.mockResolvedValue('test-message-id-123'); + // Import the module after mocks are set up const taskService = require('./task-service'); listTasks = taskService.listTasks; @@ -475,6 +484,16 @@ describe('task-service', () => { isComplete: true, }; + const existingTaskItem: TaskItem = { + pk: 'TASK#123e4567-e89b-12d3-a456-426614174000', + id: taskId, + title: 'Old Task', + detail: 'Old detail', + isComplete: false, + createdAt: '2025-11-01T10:00:00.000Z', + updatedAt: '2025-11-01T10:00:00.000Z', + }; + const updatedTaskItem: TaskItem = { pk: 'TASK#123e4567-e89b-12d3-a456-426614174000', id: taskId, @@ -486,9 +505,14 @@ describe('task-service', () => { updatedAt: '2025-12-01T10:00:00.000Z', }; - mockSend.mockResolvedValue({ - Attributes: updatedTaskItem, - }); + // First call is getTask, second call is updateTask + mockSend + .mockResolvedValueOnce({ + Item: existingTaskItem, + }) + .mockResolvedValueOnce({ + Attributes: updatedTaskItem, + }); // Act const result = await updateTask(taskId, updateTaskDto); @@ -500,7 +524,8 @@ describe('task-service', () => { expect(result?.dueAt).toBe('2025-12-31T23:59:59.000Z'); expect(result?.isComplete).toBe(true); expect(result?.updatedAt).toBe('2025-12-01T10:00:00.000Z'); - expect(mockSend).toHaveBeenCalledTimes(1); + expect(mockSend).toHaveBeenCalledTimes(2); + expect(mockPublishToTopic).toHaveBeenCalledTimes(1); expect(mockLoggerInfo).toHaveBeenCalledWith( { id: taskId, @@ -517,6 +542,16 @@ describe('task-service', () => { isComplete: false, }; + const existingTaskItem: TaskItem = { + pk: 'TASK#123e4567-e89b-12d3-a456-426614174000', + id: taskId, + title: 'Old Task', + detail: 'Old detail', + isComplete: true, + createdAt: '2025-11-01T10:00:00.000Z', + updatedAt: '2025-11-01T10:00:00.000Z', + }; + const updatedTaskItem: TaskItem = { pk: 'TASK#123e4567-e89b-12d3-a456-426614174000', id: taskId, @@ -526,9 +561,14 @@ describe('task-service', () => { updatedAt: '2025-12-01T10:00:00.000Z', }; - mockSend.mockResolvedValue({ - Attributes: updatedTaskItem, - }); + // First call is getTask, second call is updateTask + mockSend + .mockResolvedValueOnce({ + Item: existingTaskItem, + }) + .mockResolvedValueOnce({ + Attributes: updatedTaskItem, + }); // Act const result = await updateTask(taskId, updateTaskDto); @@ -539,7 +579,8 @@ describe('task-service', () => { expect(result?.detail).toBeUndefined(); expect(result?.dueAt).toBeUndefined(); expect(result?.isComplete).toBe(false); - expect(mockSend).toHaveBeenCalledTimes(1); + expect(mockSend).toHaveBeenCalledTimes(2); + expect(mockPublishToTopic).toHaveBeenCalledTimes(1); }); it('should return null when task is not found', async () => { @@ -576,6 +617,15 @@ describe('task-service', () => { isComplete: false, }; + const existingTaskItem: TaskItem = { + pk: 'TASK#123e4567-e89b-12d3-a456-426614174000', + id: taskId, + title: 'Old Task', + isComplete: true, + createdAt: '2025-11-01T10:00:00.000Z', + updatedAt: '2025-11-01T10:00:00.000Z', + }; + const updatedTaskItem: TaskItem = { pk: 'TASK#123e4567-e89b-12d3-a456-426614174000', id: taskId, @@ -585,9 +635,14 @@ describe('task-service', () => { updatedAt: '2025-12-01T10:00:00.000Z', }; - mockSend.mockResolvedValue({ - Attributes: updatedTaskItem, - }); + // First call is getTask, second call is updateTask + mockSend + .mockResolvedValueOnce({ + Item: existingTaskItem, + }) + .mockResolvedValueOnce({ + Attributes: updatedTaskItem, + }); // Act const result = await updateTask(taskId, updateTaskDto); @@ -621,6 +676,15 @@ describe('task-service', () => { isComplete: false, }; + const existingTaskItem: TaskItem = { + pk: 'TASK#123e4567-e89b-12d3-a456-426614174000', + id: taskId, + title: 'Old Task', + isComplete: true, + createdAt: '2025-11-01T10:00:00.000Z', + updatedAt: '2025-11-01T10:00:00.000Z', + }; + const updatedTaskItem: TaskItem = { pk: 'TASK#123e4567-e89b-12d3-a456-426614174000', id: taskId, @@ -630,9 +694,14 @@ describe('task-service', () => { updatedAt: '2025-12-01T10:00:00.000Z', }; - mockSend.mockResolvedValue({ - Attributes: updatedTaskItem, - }); + // First call is getTask, second call is updateTask + mockSend + .mockResolvedValueOnce({ + Item: existingTaskItem, + }) + .mockResolvedValueOnce({ + Attributes: updatedTaskItem, + }); // Act const result = await updateTask(taskId, updateTaskDto); @@ -650,24 +719,40 @@ describe('task-service', () => { isComplete: false, }; - mockSend.mockResolvedValue({ - Attributes: { - pk: 'TASK#123e4567-e89b-12d3-a456-426614174000', - id: taskId, - title: 'Updated Task', - detail: 'Updated detail', - isComplete: false, - createdAt: '2025-11-01T10:00:00.000Z', - updatedAt: '2025-12-01T10:00:00.000Z', - }, - }); + const existingTaskItem: TaskItem = { + pk: 'TASK#123e4567-e89b-12d3-a456-426614174000', + id: taskId, + title: 'Old Task', + isComplete: true, + createdAt: '2025-11-01T10:00:00.000Z', + updatedAt: '2025-11-01T10:00:00.000Z', + }; + + const updatedTaskItem: TaskItem = { + pk: 'TASK#123e4567-e89b-12d3-a456-426614174000', + id: taskId, + title: 'Updated Task', + detail: 'Updated detail', + isComplete: false, + createdAt: '2025-11-01T10:00:00.000Z', + updatedAt: '2025-12-01T10:00:00.000Z', + }; + + // First call is getTask, second call is updateTask + mockSend + .mockResolvedValueOnce({ + Item: existingTaskItem, + }) + .mockResolvedValueOnce({ + Attributes: updatedTaskItem, + }); // Act await updateTask(taskId, updateTaskDto); // Assert - expect(mockSend).toHaveBeenCalledTimes(1); - const command = mockSend.mock.calls[0][0]; + expect(mockSend).toHaveBeenCalledTimes(2); + const command = mockSend.mock.calls[1][0]; expect(command.input.TableName).toBe('test-tasks-table'); expect(command.input.Key).toEqual({ pk: 'TASK#123e4567-e89b-12d3-a456-426614174000' }); expect(command.input.ConditionExpression).toBe('attribute_exists(pk)'); @@ -683,23 +768,39 @@ describe('task-service', () => { isComplete: false, }; - mockSend.mockResolvedValue({ - Attributes: { - pk: 'TASK#123e4567-e89b-12d3-a456-426614174000', - id: taskId, - title: 'Updated Task', - detail: 'New detail', - isComplete: false, - createdAt: '2025-11-01T10:00:00.000Z', - updatedAt: '2025-12-01T10:00:00.000Z', - }, - }); + const existingTaskItem: TaskItem = { + pk: 'TASK#123e4567-e89b-12d3-a456-426614174000', + id: taskId, + title: 'Old Task', + isComplete: true, + createdAt: '2025-11-01T10:00:00.000Z', + updatedAt: '2025-11-01T10:00:00.000Z', + }; + + const updatedTaskItem: TaskItem = { + pk: 'TASK#123e4567-e89b-12d3-a456-426614174000', + id: taskId, + title: 'Updated Task', + detail: 'New detail', + isComplete: false, + createdAt: '2025-11-01T10:00:00.000Z', + updatedAt: '2025-12-01T10:00:00.000Z', + }; + + // First call is getTask, second call is updateTask + mockSend + .mockResolvedValueOnce({ + Item: existingTaskItem, + }) + .mockResolvedValueOnce({ + Attributes: updatedTaskItem, + }); // Act await updateTask(taskId, updateTaskDto); // Assert - const command = mockSend.mock.calls[0][0]; + const command = mockSend.mock.calls[1][0]; expect(command.input.UpdateExpression).toContain('detail = :detail'); expect(command.input.ExpressionAttributeValues[':detail']).toBe('New detail'); }); @@ -713,23 +814,39 @@ describe('task-service', () => { isComplete: false, }; - mockSend.mockResolvedValue({ - Attributes: { - pk: 'TASK#123e4567-e89b-12d3-a456-426614174000', - id: taskId, - title: 'Updated Task', - dueAt: '2025-12-31T23:59:59.000Z', - isComplete: false, - createdAt: '2025-11-01T10:00:00.000Z', - updatedAt: '2025-12-01T10:00:00.000Z', - }, - }); + const existingTaskItem: TaskItem = { + pk: 'TASK#123e4567-e89b-12d3-a456-426614174000', + id: taskId, + title: 'Old Task', + isComplete: true, + createdAt: '2025-11-01T10:00:00.000Z', + updatedAt: '2025-11-01T10:00:00.000Z', + }; + + const updatedTaskItem: TaskItem = { + pk: 'TASK#123e4567-e89b-12d3-a456-426614174000', + id: taskId, + title: 'Updated Task', + dueAt: '2025-12-31T23:59:59.000Z', + isComplete: false, + createdAt: '2025-11-01T10:00:00.000Z', + updatedAt: '2025-12-01T10:00:00.000Z', + }; + + // First call is getTask, second call is updateTask + mockSend + .mockResolvedValueOnce({ + Item: existingTaskItem, + }) + .mockResolvedValueOnce({ + Attributes: updatedTaskItem, + }); // Act await updateTask(taskId, updateTaskDto); // Assert - const command = mockSend.mock.calls[0][0]; + const command = mockSend.mock.calls[1][0]; expect(command.input.UpdateExpression).toContain('dueAt = :dueAt'); expect(command.input.ExpressionAttributeValues[':dueAt']).toBe('2025-12-31T23:59:59.000Z'); }); diff --git a/src/services/task-service.ts b/src/services/task-service.ts index f79f761..cb3960e 100644 --- a/src/services/task-service.ts +++ b/src/services/task-service.ts @@ -1,5 +1,6 @@ import { randomUUID } from 'crypto'; import { DeleteCommand, GetCommand, PutCommand, ScanCommand, UpdateCommand } from '@aws-sdk/lib-dynamodb'; +import { publishToTopic } from '@leanstacks/lambda-utils'; import { CreateTaskDto } from '@/models/create-task-dto.js'; import { UpdateTaskDto } from '@/models/update-task-dto.js'; @@ -123,9 +124,28 @@ export const createTask = async (createTaskDto: CreateTaskDto): Promise => // Map the created item to a Task object const task = toTask(taskItem); + logger.debug({ task }, '[TaskService] - createTask - put Task in DynamoDB'); - logger.info({ id: task.id }, '[TaskService] < createTask - successfully created task'); + // Publish task creation event to SNS + const messageId = await publishToTopic( + config.TASK_EVENT_TOPIC_ARN, + { + task, + }, + { + event: { + DataType: 'String', + StringValue: 'TaskCreated', + }, + }, + ); + logger.debug( + { taskId: task.id, topicArn: config.TASK_EVENT_TOPIC_ARN, messageId }, + '[TaskService] createTask - published TaskCreated event to SNS', + ); + // Return the created task + logger.info({ id: task.id }, '[TaskService] < createTask - successfully created task'); return task; } catch (error) { // Handle unexpected errors @@ -145,6 +165,13 @@ export const updateTask = async (id: string, updateTaskDto: UpdateTaskDto): Prom logger.info({ id }, '[TaskService] > updateTask'); try { + // Fetch existing task to ensure it exists + const existingTask = await getTask(id); + if (!existingTask) { + logger.info({ id }, '[TaskService] < updateTask - task not found'); + return null; + } + // Prepare the task item to be updated const now = new Date().toISOString(); @@ -195,7 +222,7 @@ export const updateTask = async (id: string, updateTaskDto: UpdateTaskDto): Prom ConditionExpression: 'attribute_exists(pk)', ReturnValues: 'ALL_NEW', }); - logger.debug({ input: command.input }, '[TaskService] updateTask - UpdateCommandInput'); + logger.debug({ input: command.input }, '[TaskService] updateTask - UpdateCommandInput'); // Execute the update command const response = await dynamoDocClient.send(command); @@ -208,9 +235,29 @@ export const updateTask = async (id: string, updateTaskDto: UpdateTaskDto): Prom // Map the updated item to a Task object const task = toTask(response.Attributes as TaskItem); + logger.info({ task }, '[TaskService] - updateTask - successfully updated task'); - logger.info({ id }, '[TaskService] < updateTask - successfully updated task'); + // Publish task update event to SNS + const messageId = await publishToTopic( + config.TASK_EVENT_TOPIC_ARN, + { + oldTask: existingTask, + newTask: task, + }, + { + event: { + DataType: 'String', + StringValue: 'TaskUpdated', + }, + }, + ); + logger.debug( + { taskId: id, topicArn: config.TASK_EVENT_TOPIC_ARN, messageId }, + '[TaskService] updateTask - published TaskUpdated event to SNS', + ); + // Return the updated task + logger.info({ id }, '[TaskService] < updateTask - successfully updated task'); return task; } catch (error) { // Handle conditional check failures (task not found) @@ -247,7 +294,27 @@ export const deleteTask = async (id: string): Promise => { // Execute the delete command await dynamoDocClient.send(command); + logger.info({ id }, '[TaskService] - deleteTask - deleted Task from DynamoDB'); + + // Publish task deletion event to SNS + const messageId = await publishToTopic( + config.TASK_EVENT_TOPIC_ARN, + { + taskId: id, + }, + { + event: { + DataType: 'String', + StringValue: 'TaskDeleted', + }, + }, + ); + logger.debug( + { taskId: id, topicArn: config.TASK_EVENT_TOPIC_ARN, messageId }, + '[TaskService] deleteTask - published TaskDeleted event to SNS', + ); + // Return true indicating successful deletion logger.info({ id }, '[TaskService] < deleteTask - successfully deleted task'); return true; } catch (error) { diff --git a/src/utils/sns-client.test.ts b/src/utils/sns-client.test.ts deleted file mode 100644 index fdb4341..0000000 --- a/src/utils/sns-client.test.ts +++ /dev/null @@ -1,301 +0,0 @@ -import { SNSClient } from '@aws-sdk/client-sns'; - -// Mock the SNS client and logger before importing the module under test -const mockSend = jest.fn(); -const mockLoggerDebug = jest.fn(); -const mockLoggerError = jest.fn(); - -jest.mock('@aws-sdk/client-sns', () => { - const actualModule = jest.requireActual('@aws-sdk/client-sns'); - return { - ...actualModule, - SNSClient: jest.fn(), - }; -}); - -jest.mock('./logger.js', () => ({ - logger: { - debug: mockLoggerDebug, - info: jest.fn(), - warn: jest.fn(), - error: mockLoggerError, - }, -})); - -jest.mock('./config.js', () => ({ - config: { - TASKS_TABLE: 'test-tasks-table', - TASK_TOPIC_ARN: 'arn:aws:sns:us-east-1:123456789012:test-task-topic', - AWS_REGION: 'us-east-1', - LOGGING_ENABLED: true, - LOGGING_LEVEL: 'debug', - LOGGING_FORMAT: 'json', - CORS_ALLOW_ORIGIN: '*', - }, -})); - -describe('sns-client', () => { - let publishToTopic: typeof import('./sns-client').publishToTopic; - - beforeEach(() => { - jest.clearAllMocks(); - - // Mock SNSClient constructor - (SNSClient as jest.Mock).mockImplementation(() => ({ - send: mockSend, - })); - - // Import after mocks are set up - const snsClient = require('./sns-client'); - publishToTopic = snsClient.publishToTopic; - }); - - describe('publishToTopic', () => { - it('should publish a message to SNS topic successfully', async () => { - // Arrange - const topicArn = 'arn:aws:sns:us-east-1:123456789012:test-topic'; - const message = { action: 'task_created', payload: { taskId: '123' } }; - - mockSend.mockResolvedValue({ - MessageId: 'message-id-123', - }); - - // Act - const result = await publishToTopic(topicArn, message); - - // Assert - expect(result).toBe('message-id-123'); - expect(mockSend).toHaveBeenCalledTimes(1); - expect(mockLoggerDebug).toHaveBeenCalledWith( - expect.objectContaining({ topicArn }), - '[SnsClient] > publishToTopic', - ); - }); - - it('should convert message object to JSON string', async () => { - // Arrange - const topicArn = 'arn:aws:sns:us-east-1:123456789012:test-topic'; - const message = { action: 'task_updated', payload: { taskId: '456' } }; - - mockSend.mockResolvedValue({ - MessageId: 'message-id-456', - }); - - // Act - await publishToTopic(topicArn, message); - - // Assert - const publishCommand = mockSend.mock.calls[0][0]; - expect(publishCommand.input.Message).toBe(JSON.stringify(message)); - }); - - it('should include message attributes when provided', async () => { - // Arrange - const topicArn = 'arn:aws:sns:us-east-1:123456789012:test-topic'; - const message = { action: 'task_created' }; - const attributes = { - eventType: { - DataType: 'String' as const, - StringValue: 'task_created', - }, - }; - - mockSend.mockResolvedValue({ - MessageId: 'message-id-789', - }); - - // Act - await publishToTopic(topicArn, message, attributes); - - // Assert - const publishCommand = mockSend.mock.calls[0][0]; - expect(publishCommand.input.MessageAttributes).toEqual(attributes); - }); - - it('should return empty string when MessageId is undefined', async () => { - // Arrange - const topicArn = 'arn:aws:sns:us-east-1:123456789012:test-topic'; - const message = { action: 'test' }; - - mockSend.mockResolvedValue({ - MessageId: undefined, - }); - - // Act - const result = await publishToTopic(topicArn, message); - - // Assert - expect(result).toBe(''); - }); - - it('should log publish success with message details', async () => { - // Arrange - const topicArn = 'arn:aws:sns:us-east-1:123456789012:test-topic'; - const message = { action: 'task_deleted' }; - - mockSend.mockResolvedValue({ - MessageId: 'msg-delete-123', - }); - - // Act - await publishToTopic(topicArn, message); - - // Assert - expect(mockLoggerDebug).toHaveBeenCalledWith( - expect.objectContaining({ - topicArn, - messageId: 'msg-delete-123', - }), - '[SnsClient] < publishToTopic - successfully published message', - ); - }); - - it('should handle SNS publish errors and rethrow them', async () => { - // Arrange - const topicArn = 'arn:aws:sns:us-east-1:123456789012:test-topic'; - const message = { action: 'test' }; - const mockError = new Error('SNS publish failed'); - - mockSend.mockRejectedValue(mockError); - - // Act & Assert - await expect(publishToTopic(topicArn, message)).rejects.toThrow('SNS publish failed'); - expect(mockLoggerError).toHaveBeenCalledWith( - expect.objectContaining({ - error: mockError, - topicArn, - }), - '[SnsClient] < publishToTopic - failed to publish message to SNS', - ); - }); - - it('should handle complex message payloads', async () => { - // Arrange - const topicArn = 'arn:aws:sns:us-east-1:123456789012:test-topic'; - const message = { - action: 'task_created', - payload: { - task: { - id: 'task-123', - title: 'New Task', - detail: 'Task details', - isComplete: false, - createdAt: '2025-12-01T10:00:00.000Z', - updatedAt: '2025-12-01T10:00:00.000Z', - }, - }, - timestamp: '2025-12-01T10:00:00.000Z', - }; - - mockSend.mockResolvedValue({ - MessageId: 'complex-msg-id', - }); - - // Act - const result = await publishToTopic(topicArn, message); - - // Assert - expect(result).toBe('complex-msg-id'); - const publishCommand = mockSend.mock.calls[0][0]; - const publishedMessage = JSON.parse(publishCommand.input.Message); - expect(publishedMessage.action).toBe('task_created'); - expect(publishedMessage.payload.task.title).toBe('New Task'); - }); - - it('should handle messages with empty objects', async () => { - // Arrange - const topicArn = 'arn:aws:sns:us-east-1:123456789012:test-topic'; - const message = {}; - - mockSend.mockResolvedValue({ - MessageId: 'empty-msg-id', - }); - - // Act - const result = await publishToTopic(topicArn, message); - - // Assert - expect(result).toBe('empty-msg-id'); - const publishCommand = mockSend.mock.calls[0][0]; - expect(publishCommand.input.Message).toBe('{}'); - }); - - it('should not include message attributes when not provided', async () => { - // Arrange - const topicArn = 'arn:aws:sns:us-east-1:123456789012:test-topic'; - const message = { action: 'test' }; - - mockSend.mockResolvedValue({ - MessageId: 'msg-no-attrs', - }); - - // Act - await publishToTopic(topicArn, message); - - // Assert - const publishCommand = mockSend.mock.calls[0][0]; - expect(publishCommand.input.MessageAttributes).toBeUndefined(); - }); - - it('should use correct topic ARN in publish call', async () => { - // Arrange - const topicArn = 'arn:aws:sns:us-west-2:987654321098:custom-topic'; - const message = { action: 'test' }; - - mockSend.mockResolvedValue({ - MessageId: 'custom-topic-msg', - }); - - // Act - await publishToTopic(topicArn, message); - - // Assert - const publishCommand = mockSend.mock.calls[0][0]; - expect(publishCommand.input.TopicArn).toBe(topicArn); - }); - }); - - describe('MessageAttributes interface', () => { - it('should allow String type attributes', async () => { - // Arrange - const topicArn = 'arn:aws:sns:us-east-1:123456789012:test-topic'; - const message = { action: 'test' }; - const attributes = { - eventType: { - DataType: 'String' as const, - StringValue: 'task_event', - }, - }; - - mockSend.mockResolvedValue({ MessageId: 'test-msg' }); - - // Act - const result = await publishToTopic(topicArn, message, attributes); - - // Assert - expect(result).toBe('test-msg'); - const publishCommand = mockSend.mock.calls[0][0]; - expect(publishCommand.input.MessageAttributes.eventType.DataType).toBe('String'); - }); - - it('should allow Number type attributes', async () => { - // Arrange - const topicArn = 'arn:aws:sns:us-east-1:123456789012:test-topic'; - const message = { action: 'test' }; - const attributes = { - priority: { - DataType: 'Number' as const, - StringValue: '1', - }, - }; - - mockSend.mockResolvedValue({ MessageId: 'test-msg' }); - - // Act - const result = await publishToTopic(topicArn, message, attributes); - - // Assert - expect(result).toBe('test-msg'); - }); - }); -}); diff --git a/src/utils/sns-client.ts b/src/utils/sns-client.ts deleted file mode 100644 index cba7a2a..0000000 --- a/src/utils/sns-client.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { MessageAttributeValue, PublishCommand, SNSClient } from '@aws-sdk/client-sns'; - -import { config } from './config'; -import { logger } from './logger'; - -/** - * SNS client instance for publishing messages to SNS topics. - */ -const _snsClient = new SNSClient({ - region: config.AWS_REGION, -}); - -/** - * Interface for SNS message attributes. - */ -export interface MessageAttributes { - [key: string]: MessageAttributeValue; -} - -/** - * Publishes a message to an SNS topic. - * @param topicArn - The ARN of the SNS topic to publish to - * @param message - The message content (will be converted to JSON string) - * @param attributes - Optional message attributes for filtering - * @returns Promise that resolves to the message ID - * @throws Error if the SNS publish operation fails - */ -export const publishToTopic = async ( - topicArn: string, - message: Record, - attributes?: MessageAttributes, -): Promise => { - logger.debug({ topicArn }, '[SnsClient] > publishToTopic'); - - try { - // Create the PublishCommand with the message and attributes - const command = new PublishCommand({ - TopicArn: topicArn, - Message: JSON.stringify(message), - MessageAttributes: attributes, - }); - - logger.debug({ command }, '[SnsClient] publishToTopic - PublishCommand'); - - // Send the publish command - const response = await _snsClient.send(command); - - logger.debug( - { topicArn, messageId: response.MessageId }, - '[SnsClient] < publishToTopic - successfully published message', - ); - - return response.MessageId ?? ''; - } catch (error) { - // Handle publish errors - logger.error( - { error: error as Error, topicArn }, - '[SnsClient] < publishToTopic - failed to publish message to SNS', - ); - throw error; - } -}; From 07170e04e24c65ad522b5127d0dcaee45ec56503 Mon Sep 17 00:00:00 2001 From: Matthew Warman Date: Wed, 24 Dec 2025 07:56:51 -0500 Subject: [PATCH 8/9] feat: add Lambda Utils project overview and resources to README --- README.md | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ee81171..c6a02f3 100644 --- a/README.md +++ b/README.md @@ -158,10 +158,35 @@ The project supports multiple environments: Each environment has its own AWS account and configuration. +## Lambda Utils Project + +The `@leanstacks/lambda-utils` package is a TypeScript utility library for AWS Lambda functions. It provides pre-configured logging, API response formatting, configuration validation, and AWS SDK clients—reducing boilerplate and promoting best practices within Node.js Lambda functions. + +Several of the Lambda Utils are used in the Lambda Starter application. You are encouraged to use the Lambda Utils library in your project or, if you want to maintain the source code yourself, you may fork the repo or copy only the code you need into your project. + +Learn more about the Lambda Utils with these resources... + +- **[@leanstacks/lambda-utils package on NPM](https://www.npmjs.com/package/@leanstacks/lambda-utils)** +- **[lambda-utils repository on GitHub](https://github.com/leanstacks/lambda-utils)** + +## Serverless Microservice Patterns + +This project implements the **Simple Web Service** serverless microservice pattern. The [Serverless Microservice Patterns repository](https://github.com/leanstacks/serverless-microservice-patterns) provides a comprehensive collection of additional patterns and examples, including: + +- **Simple Web Service**: A basic serverless web service pattern using API Gateway, Lambda, and DynamoDB. +- **Gatekeeper**: Adds an Auth microservice to authenticate and authorize API requests. +- **Internal API**: Facilitates synchronous, internal microservice-to-microservice integration without API Gateway exposure. +- **Internal Handoff**: Enables asynchronous microservice-to-microservice communication. +- **Publish Subscribe**: Demonstrates event-driven architecture using SNS topics and SQS queues for loose coupling. +- **Queue-Based Load Leveling**: Uses a message queue as a buffer to decouple producers from consumers and smooth demand spikes. + +Each pattern is implemented as a standalone project with practical examples and reference implementations for building scalable, event-driven microservices on AWS. + ## License This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. ## Further Reading -- [Project Documentation](./docs/README.md) +- [**Lambda Utils Project**](https://github.com/leanstacks/lambda-utils) +- [**Project Documentation**](./docs/README.md) From 282eea579508f659cb7c5a75aa7ce3971f134a62 Mon Sep 17 00:00:00 2001 From: Matthew Warman Date: Wed, 24 Dec 2025 08:01:41 -0500 Subject: [PATCH 9/9] refactor: remove lambda-client implementation and associated tests --- src/utils/lambda-client.test.ts | 685 -------------------------------- src/utils/lambda-client.ts | 113 ------ 2 files changed, 798 deletions(-) delete mode 100644 src/utils/lambda-client.test.ts delete mode 100644 src/utils/lambda-client.ts diff --git a/src/utils/lambda-client.test.ts b/src/utils/lambda-client.test.ts deleted file mode 100644 index ae980b2..0000000 --- a/src/utils/lambda-client.test.ts +++ /dev/null @@ -1,685 +0,0 @@ -// Mock the logger -const mockLoggerInfo = jest.fn(); -const mockLoggerDebug = jest.fn(); -const mockLoggerError = jest.fn(); - -jest.mock('./logger.js', () => ({ - logger: { - info: mockLoggerInfo, - debug: mockLoggerDebug, - error: mockLoggerError, - }, -})); - -// Mock the config module -jest.mock('./config.js', () => ({ - config: { - AWS_REGION: 'us-east-1', - }, -})); - -// Mock the Lambda client -let mockSend: jest.Mock; -jest.mock('@aws-sdk/client-lambda', () => { - mockSend = jest.fn(); - return { - InvokeCommand: jest.fn(), - LambdaClient: jest.fn().mockImplementation(() => ({ - send: mockSend, - })), - }; -}); - -import { invokeLambdaSync, invokeLambdaAsync } from './lambda-client.js'; - -/** - * Test suite for Lambda client utility - */ -describe('lambda-client', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - describe('invokeLambdaSync', () => { - it('should successfully invoke a Lambda function with RequestResponse invocation type', async () => { - // Arrange - const functionName = 'test-function'; - const payload = { test: 'data' }; - const mockResponse = { result: 'success' }; - - mockSend.mockResolvedValueOnce({ - StatusCode: 200, - FunctionError: undefined, - Payload: new TextEncoder().encode(JSON.stringify(mockResponse)), - }); - - // Act - const result = await invokeLambdaSync(functionName, payload); - - // Assert - expect(result).toEqual(mockResponse); - expect(mockLoggerInfo).toHaveBeenCalledWith( - expect.objectContaining({ functionName }), - '[LambdaClient] > invokeLambdaSync', - ); - expect(mockLoggerInfo).toHaveBeenCalledWith( - expect.objectContaining({ - functionName, - statusCode: 200, - }), - '[LambdaClient] < invokeLambdaSync - successfully invoked Lambda function', - ); - }); - - it('should serialize payload to JSON string', async () => { - // Arrange - const functionName = 'test-function'; - const payload = { httpMethod: 'GET', path: '/tasks', body: null }; - - mockSend.mockResolvedValueOnce({ - StatusCode: 200, - FunctionError: undefined, - Payload: new TextEncoder().encode(JSON.stringify([])), - }); - - // Act - await invokeLambdaSync(functionName, payload); - - // Assert - expect(mockSend).toHaveBeenCalled(); - }); - - it('should deserialize response payload from Uint8Array', async () => { - // Arrange - const functionName = 'test-function'; - const payload = {}; - const mockResponse = { - statusCode: 200, - body: JSON.stringify({ data: 'test' }), - headers: { 'Content-Type': 'application/json' }, - }; - - mockSend.mockResolvedValueOnce({ - StatusCode: 200, - FunctionError: undefined, - Payload: new TextEncoder().encode(JSON.stringify(mockResponse)), - }); - - // Act - const result = (await invokeLambdaSync(functionName, payload)) as Record; - - // Assert - expect(result).toEqual(mockResponse); - expect(typeof result).toBe('object'); - expect(result.statusCode).toBe(200); - }); - - it('should handle empty Payload from Lambda response', async () => { - // Arrange - const functionName = 'test-function'; - const payload = {}; - - mockSend.mockResolvedValueOnce({ - StatusCode: 200, - FunctionError: undefined, - Payload: undefined, - }); - - // Act - const result = await invokeLambdaSync(functionName, payload); - - // Assert - expect(result).toBeNull(); - }); - - it('should throw error when Lambda function returns FunctionError', async () => { - // Arrange - const functionName = 'test-function'; - const payload = {}; - const errorResponse = { message: 'Internal error' }; - - mockSend.mockResolvedValueOnce({ - StatusCode: 200, - FunctionError: 'Unhandled', - Payload: new TextEncoder().encode(JSON.stringify(errorResponse)), - }); - - // Act & Assert - await expect(invokeLambdaSync(functionName, payload)).rejects.toThrow('Lambda function error: Unhandled'); - expect(mockLoggerError).toHaveBeenCalledWith( - expect.objectContaining({ - functionName, - FunctionError: 'Unhandled', - responsePayload: expect.any(Object), - }), - '[LambdaClient] < invokeLambdaSync - Lambda function returned an error', - ); - }); - - it('should handle Lambda SDK invocation errors', async () => { - // Arrange - const functionName = 'non-existent-function'; - const payload = {}; - const error = new Error('Function not found'); - - mockSend.mockRejectedValueOnce(error); - - // Act & Assert - await expect(invokeLambdaSync(functionName, payload)).rejects.toThrow('Function not found'); - expect(mockLoggerError).toHaveBeenCalledWith( - expect.objectContaining({ - error, - functionName, - }), - '[LambdaClient] < invokeLambdaSync - failed to invoke Lambda function', - ); - }); - - it('should support generic type parameter for response', async () => { - // Arrange - interface TaskResponse { - tasks: { id: string; title: string }[]; - } - - const functionName = 'list-tasks'; - const payload = {}; - const mockResponse: TaskResponse = { - tasks: [{ id: '1', title: 'Test Task' }], - }; - - mockSend.mockResolvedValueOnce({ - StatusCode: 200, - FunctionError: undefined, - Payload: new TextEncoder().encode(JSON.stringify(mockResponse)), - }); - - // Act - const result = await invokeLambdaSync(functionName, payload); - - // Assert - expect(result).toEqual(mockResponse); - const typedResult = result as TaskResponse | null; - expect(typedResult?.tasks).toBeDefined(); - }); - - it('should log debug information during invocation', async () => { - // Arrange - const functionName = 'test-function'; - const payload = { test: 'data' }; - - mockSend.mockResolvedValueOnce({ - StatusCode: 200, - FunctionError: undefined, - Payload: new TextEncoder().encode(JSON.stringify({})), - }); - - // Act - await invokeLambdaSync(functionName, payload); - - // Assert - expect(mockLoggerDebug).toHaveBeenCalledWith( - expect.any(Object), - '[LambdaClient] invokeLambdaSync - InvokeCommand', - ); - }); - - it('should handle complex nested payloads', async () => { - // Arrange - const functionName = 'process-data'; - const complexPayload = { - event: { - httpMethod: 'POST', - path: '/api/v1/tasks', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ title: 'New Task', due: '2024-12-25' }), - requestContext: { - requestId: 'req-123', - accountId: '123456789012', - }, - }, - context: { - functionName: 'processor', - memoryLimit: 256, - }, - }; - - const mockResponse = { success: true, id: 'task-123' }; - - mockSend.mockResolvedValueOnce({ - StatusCode: 200, - FunctionError: undefined, - Payload: new TextEncoder().encode(JSON.stringify(mockResponse)), - }); - - // Act - const result = await invokeLambdaSync(functionName, complexPayload); - - // Assert - expect(result).toEqual(mockResponse); - }); - - it('should use RequestResponse invocation type', async () => { - // Arrange - const functionName = 'sync-function'; - const payload = {}; - - mockSend.mockResolvedValueOnce({ - StatusCode: 200, - FunctionError: undefined, - Payload: new TextEncoder().encode(JSON.stringify({ status: 'ok' })), - }); - - // Act - await invokeLambdaSync(functionName, payload); - - // Assert - expect(mockSend).toHaveBeenCalled(); - }); - - it('should handle Lambda response with non-JSON payload', async () => { - // Arrange - const functionName = 'text-function'; - const payload = {}; - - mockSend.mockResolvedValueOnce({ - StatusCode: 200, - FunctionError: undefined, - Payload: new TextEncoder().encode('plain text response'), - }); - - // Act & Assert - await expect(invokeLambdaSync(functionName, payload)).rejects.toThrow(); - }); - - it('should handle successful invocation with HTTP status codes other than 200', async () => { - // Arrange - const functionName = 'api-function'; - const payload = {}; - const mockResponse = { - statusCode: 404, - body: JSON.stringify({ message: 'Not Found' }), - }; - - mockSend.mockResolvedValueOnce({ - StatusCode: 202, - FunctionError: undefined, - Payload: new TextEncoder().encode(JSON.stringify(mockResponse)), - }); - - // Act - const result = (await invokeLambdaSync(functionName, payload)) as Record; - - // Assert - expect(result).toEqual(mockResponse); - expect(result.statusCode).toBe(404); - }); - - it('should include function name in log messages', async () => { - // Arrange - const functionName = 'my-special-function'; - const payload = {}; - - mockSend.mockResolvedValueOnce({ - StatusCode: 200, - FunctionError: undefined, - Payload: new TextEncoder().encode(JSON.stringify({})), - }); - - // Act - await invokeLambdaSync(functionName, payload); - - // Assert - expect(mockLoggerInfo).toHaveBeenCalledWith( - expect.objectContaining({ functionName }), - '[LambdaClient] > invokeLambdaSync', - ); - expect(mockLoggerDebug).toHaveBeenCalledWith( - expect.any(Object), - '[LambdaClient] invokeLambdaSync - InvokeCommand', - ); - expect(mockLoggerInfo).toHaveBeenCalledWith( - expect.objectContaining({ - functionName, - statusCode: 200, - }), - '[LambdaClient] < invokeLambdaSync - successfully invoked Lambda function', - ); - }); - }); - - describe('invokeLambdaAsync', () => { - it('should successfully invoke a Lambda function with Event invocation type', async () => { - // Arrange - const functionName = 'async-test-function'; - const payload = { test: 'data' }; - - mockSend.mockResolvedValueOnce({ - StatusCode: 202, - FunctionError: undefined, - Payload: new TextEncoder().encode(JSON.stringify({ result: 'accepted' })), - }); - - // Act - await invokeLambdaAsync(functionName, payload); - - // Assert - expect(mockLoggerInfo).toHaveBeenCalledWith( - expect.objectContaining({ functionName }), - '[LambdaClient] > invokeLambdaAsync', - ); - expect(mockLoggerInfo).toHaveBeenCalledWith( - expect.objectContaining({ - functionName, - statusCode: 202, - }), - '[LambdaClient] < invokeLambdaAsync - successfully invoked Lambda function', - ); - }); - - it('should serialize payload to JSON string for async invocation', async () => { - // Arrange - const functionName = 'async-test-function'; - const payload = { httpMethod: 'POST', path: '/tasks', body: { title: 'New Task' } }; - - mockSend.mockResolvedValueOnce({ - StatusCode: 202, - FunctionError: undefined, - Payload: new TextEncoder().encode(JSON.stringify({})), - }); - - // Act - await invokeLambdaAsync(functionName, payload); - - // Assert - expect(mockSend).toHaveBeenCalled(); - }); - - it('should deserialize response payload from Uint8Array for async invocation', async () => { - // Arrange - const functionName = 'async-test-function'; - const payload = {}; - - mockSend.mockResolvedValueOnce({ - StatusCode: 202, - FunctionError: undefined, - Payload: new TextEncoder().encode( - JSON.stringify({ - statusCode: 202, - body: JSON.stringify({ queued: true }), - headers: { 'Content-Type': 'application/json' }, - }), - ), - }); - - // Act - await invokeLambdaAsync(functionName, payload); - - // Assert - expect(mockSend).toHaveBeenCalled(); - expect(mockLoggerInfo).toHaveBeenCalledWith( - expect.objectContaining({ - functionName, - statusCode: 202, - }), - '[LambdaClient] < invokeLambdaAsync - successfully invoked Lambda function', - ); - }); - - it('should handle empty Payload from async Lambda response', async () => { - // Arrange - const functionName = 'async-test-function'; - const payload = {}; - - mockSend.mockResolvedValueOnce({ - StatusCode: 202, - FunctionError: undefined, - Payload: undefined, - }); - - // Act - await invokeLambdaAsync(functionName, payload); - - // Assert - expect(mockLoggerInfo).toHaveBeenCalledWith( - expect.objectContaining({ - functionName, - statusCode: 202, - }), - '[LambdaClient] < invokeLambdaAsync - successfully invoked Lambda function', - ); - }); - - it('should throw error when async Lambda function returns FunctionError', async () => { - // Arrange - const functionName = 'async-test-function'; - const payload = {}; - const errorResponse = { message: 'Internal error' }; - - mockSend.mockResolvedValueOnce({ - StatusCode: 202, - FunctionError: 'Unhandled', - Payload: new TextEncoder().encode(JSON.stringify(errorResponse)), - }); - - // Act & Assert - await expect(invokeLambdaAsync(functionName, payload)).rejects.toThrow('Lambda function error: Unhandled'); - expect(mockLoggerError).toHaveBeenCalledWith( - expect.objectContaining({ - functionName, - FunctionError: 'Unhandled', - response: expect.objectContaining({ - FunctionError: 'Unhandled', - }), - }), - '[LambdaClient] < invokeLambdaAsync - Lambda function returned an error', - ); - }); - - it('should handle Lambda SDK invocation errors for async invocation', async () => { - // Arrange - const functionName = 'non-existent-async-function'; - const payload = {}; - const error = new Error('Function not found'); - - mockSend.mockRejectedValueOnce(error); - - // Act & Assert - await expect(invokeLambdaAsync(functionName, payload)).rejects.toThrow('Function not found'); - expect(mockLoggerError).toHaveBeenCalledWith( - expect.objectContaining({ - error, - functionName, - }), - '[LambdaClient] < invokeLambdaAsync - failed to invoke Lambda function', - ); - }); - - it('should support generic type parameter for async response', async () => { - // Arrange - const functionName = 'create-task-async'; - const payload = {}; - - mockSend.mockResolvedValueOnce({ - StatusCode: 202, - FunctionError: undefined, - Payload: new TextEncoder().encode( - JSON.stringify({ - jobId: 'job-123', - status: 'queued', - }), - ), - }); - - // Act - await invokeLambdaAsync(functionName, payload); - - // Assert - invokeLambdaAsync returns void - expect(mockLoggerInfo).toHaveBeenCalledWith( - expect.objectContaining({ - functionName, - statusCode: 202, - }), - '[LambdaClient] < invokeLambdaAsync - successfully invoked Lambda function', - ); - }); - - it('should log debug information during async invocation', async () => { - // Arrange - const functionName = 'async-test-function'; - const payload = { test: 'data' }; - - mockSend.mockResolvedValueOnce({ - StatusCode: 202, - FunctionError: undefined, - Payload: new TextEncoder().encode(JSON.stringify({})), - }); - - // Act - await invokeLambdaAsync(functionName, payload); - - // Assert - expect(mockLoggerDebug).toHaveBeenCalledWith( - expect.any(Object), - '[LambdaClient] invokeLambdaAsync - InvokeCommand', - ); - }); - - it('should handle complex nested payloads for async invocation', async () => { - // Arrange - const functionName = 'process-data-async'; - const complexPayload = { - event: { - httpMethod: 'POST', - path: '/api/v1/tasks', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ title: 'Background Task', priority: 'high' }), - requestContext: { - requestId: 'req-456', - accountId: '123456789012', - }, - }, - context: { - functionName: 'async-processor', - memoryLimit: 512, - }, - }; - - mockSend.mockResolvedValueOnce({ - StatusCode: 202, - FunctionError: undefined, - Payload: new TextEncoder().encode(JSON.stringify({ jobId: 'async-job-456', queued: true })), - }); - - // Act - await invokeLambdaAsync(functionName, complexPayload); - - // Assert - expect(mockLoggerInfo).toHaveBeenCalledWith( - expect.objectContaining({ - functionName, - statusCode: 202, - }), - '[LambdaClient] < invokeLambdaAsync - successfully invoked Lambda function', - ); - }); - - it('should use Event invocation type for async invocation', async () => { - // Arrange - const functionName = 'event-function'; - const payload = {}; - - mockSend.mockResolvedValueOnce({ - StatusCode: 202, - FunctionError: undefined, - Payload: new TextEncoder().encode(JSON.stringify({ status: 'queued' })), - }); - - // Act - await invokeLambdaAsync(functionName, payload); - - // Assert - expect(mockSend).toHaveBeenCalled(); - }); - - it('should handle Lambda async response with non-JSON payload', async () => { - // Arrange - const functionName = 'text-async-function'; - const payload = {}; - - mockSend.mockResolvedValueOnce({ - StatusCode: 202, - FunctionError: undefined, - Payload: new TextEncoder().encode('plain text response'), - }); - - // Act & Assert - invokeLambdaAsync doesn't parse payloads for async - await invokeLambdaAsync(functionName, payload); - - expect(mockLoggerInfo).toHaveBeenCalledWith( - expect.objectContaining({ - functionName, - statusCode: 202, - }), - '[LambdaClient] < invokeLambdaAsync - successfully invoked Lambda function', - ); - }); - - it('should handle successful async invocation with various HTTP status codes', async () => { - // Arrange - const functionName = 'api-async-function'; - const payload = {}; - - mockSend.mockResolvedValueOnce({ - StatusCode: 202, - FunctionError: undefined, - Payload: new TextEncoder().encode( - JSON.stringify({ - statusCode: 202, - body: JSON.stringify({ message: 'Accepted' }), - }), - ), - }); - - // Act - await invokeLambdaAsync(functionName, payload); - - // Assert - expect(mockLoggerInfo).toHaveBeenCalledWith( - expect.objectContaining({ - functionName, - statusCode: 202, - }), - '[LambdaClient] < invokeLambdaAsync - successfully invoked Lambda function', - ); - }); - - it('should include function name in async log messages', async () => { - // Arrange - const functionName = 'my-async-special-function'; - const payload = {}; - - mockSend.mockResolvedValueOnce({ - StatusCode: 202, - FunctionError: undefined, - Payload: new TextEncoder().encode(JSON.stringify({})), - }); - - // Act - await invokeLambdaAsync(functionName, payload); - - // Assert - expect(mockLoggerInfo).toHaveBeenCalledWith({ functionName }, '[LambdaClient] > invokeLambdaAsync'); - expect(mockLoggerDebug).toHaveBeenCalledWith( - expect.any(Object), - '[LambdaClient] invokeLambdaAsync - InvokeCommand', - ); - expect(mockLoggerInfo).toHaveBeenCalledWith( - { - functionName, - statusCode: 202, - }, - '[LambdaClient] < invokeLambdaAsync - successfully invoked Lambda function', - ); - }); - }); -}); diff --git a/src/utils/lambda-client.ts b/src/utils/lambda-client.ts deleted file mode 100644 index 7184ed0..0000000 --- a/src/utils/lambda-client.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { InvokeCommand, LambdaClient } from '@aws-sdk/client-lambda'; - -import { config } from './config'; -import { logger } from './logger'; - -/** - * AWS Lambda service client - */ -const _lambdaClient = new LambdaClient({ region: config.AWS_REGION }); - -/** - * Type representing a JSON payload for Lambda invocation - */ -export type JsonPayload = Record | Array; - -/** - * Invokes a Lambda function synchronously (RequestResponse) - * @param functionName - The name or ARN of the Lambda function to invoke - * @param payload - The JSON payload to pass to the Lambda function - * @returns The response payload from the Lambda function - * @throws Error if the Lambda invocation fails - */ -export const invokeLambdaSync = async (functionName: string, payload: JsonPayload): Promise => { - logger.info({ functionName }, '[LambdaClient] > invokeLambdaSync'); - - try { - // Create the InvokeCommand with RequestResponse invocation type - const command = new InvokeCommand({ - FunctionName: functionName, - InvocationType: 'RequestResponse', - Payload: JSON.stringify(payload), - }); - - logger.debug({ command }, '[LambdaClient] invokeLambdaSync - InvokeCommand'); - - // Send the command to invoke the Lambda function - const response = await _lambdaClient.send(command); - - // Parse the response payload - const responsePayload = response.Payload ? JSON.parse(new TextDecoder().decode(response.Payload)) : null; - - // Check for function errors - if (response.FunctionError) { - logger.error( - { - functionName, - FunctionError: response.FunctionError, - responsePayload, - }, - '[LambdaClient] < invokeLambdaSync - Lambda function returned an error', - ); - throw new Error(`Lambda function error: ${response.FunctionError}`); - } - - logger.info( - { functionName, statusCode: response.StatusCode }, - '[LambdaClient] < invokeLambdaSync - successfully invoked Lambda function', - ); - return responsePayload as T; - } catch (error) { - // Handle invocation errors - logger.error( - { error: error as Error, functionName }, - '[LambdaClient] < invokeLambdaSync - failed to invoke Lambda function', - ); - throw error; - } -}; - -/** - * Invokes a Lambda function asynchronously (Event) - * @param functionName - The name or ARN of the Lambda function to invoke - * @param payload - The JSON payload to pass to the Lambda function - * @throws Error if the Lambda invocation fails - */ -export const invokeLambdaAsync = async (functionName: string, payload: JsonPayload): Promise => { - logger.info({ functionName }, '[LambdaClient] > invokeLambdaAsync'); - - try { - // Create the InvokeCommand with Event invocation type - const command = new InvokeCommand({ - FunctionName: functionName, - InvocationType: 'Event', - Payload: JSON.stringify(payload), - }); - - logger.debug({ command }, '[LambdaClient] invokeLambdaAsync - InvokeCommand'); - - // Send the command to invoke the Lambda function - const response = await _lambdaClient.send(command); - - // Check for function errors - if (response.FunctionError) { - logger.error( - { functionName, FunctionError: response.FunctionError, response }, - '[LambdaClient] < invokeLambdaAsync - Lambda function returned an error', - ); - throw new Error(`Lambda function error: ${response.FunctionError}`); - } - - logger.info( - { functionName, statusCode: response.StatusCode }, - '[LambdaClient] < invokeLambdaAsync - successfully invoked Lambda function', - ); - } catch (error) { - // Handle invocation errors - logger.error( - { error: error as Error, functionName }, - '[LambdaClient] < invokeLambdaAsync - failed to invoke Lambda function', - ); - throw error; - } -};