From 236fd8ae88031c8a50c0b5a36773a9b541b8bd96 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Wed, 3 Jan 2024 18:22:34 +0100 Subject: [PATCH 01/23] WIP: parser --- docs/snippets/package.json | 3 +- docs/snippets/parser/decorator.ts | 32 ++++ docs/snippets/parser/envelopeDecorator.ts | 34 ++++ docs/snippets/parser/envelopeMiddy.ts | 34 ++++ docs/snippets/parser/examplePayload.json | 21 ++ docs/snippets/parser/extend.ts | 38 ++++ docs/snippets/parser/manual.ts | 30 +++ docs/snippets/parser/middy.ts | 33 ++++ docs/snippets/parser/schema.ts | 16 ++ docs/snippets/tsconfig.json | 2 + docs/utilities/parser.md | 180 ++++++++++++++++++ mkdocs.yml | 1 + packages/parser/package.json | 12 ++ packages/parser/src/envelopes/dynamodb.ts | 2 +- packages/parser/src/envelopes/index.ts | 13 ++ packages/parser/src/index.ts | 1 + packages/parser/src/schemas/index.ts | 34 ++++ packages/parser/src/types/envelope.ts | 4 +- .../tests/unit/envelopes/dynamodb.test.ts | 4 +- 19 files changed, 488 insertions(+), 6 deletions(-) create mode 100644 docs/snippets/parser/decorator.ts create mode 100644 docs/snippets/parser/envelopeDecorator.ts create mode 100644 docs/snippets/parser/envelopeMiddy.ts create mode 100644 docs/snippets/parser/examplePayload.json create mode 100644 docs/snippets/parser/extend.ts create mode 100644 docs/snippets/parser/manual.ts create mode 100644 docs/snippets/parser/middy.ts create mode 100644 docs/snippets/parser/schema.ts create mode 100644 docs/utilities/parser.md create mode 100644 packages/parser/src/envelopes/index.ts create mode 100644 packages/parser/src/schemas/index.ts diff --git a/docs/snippets/package.json b/docs/snippets/package.json index 94b9aaac9a..e017b77ff0 100644 --- a/docs/snippets/package.json +++ b/docs/snippets/package.json @@ -37,6 +37,7 @@ "aws-sdk-client-mock": "^3.0.0", "aws-sdk-client-mock-jest": "^3.0.0", "axios": "^1.5.0", - "hashi-vault-js": "^0.4.14" + "hashi-vault-js": "^0.4.14", + "zod": "^3.22.4" } } diff --git a/docs/snippets/parser/decorator.ts b/docs/snippets/parser/decorator.ts new file mode 100644 index 0000000000..585206b1bc --- /dev/null +++ b/docs/snippets/parser/decorator.ts @@ -0,0 +1,32 @@ +import { Context } from 'aws-lambda'; +import { LambdaInterface } from '@aws-lambda-powertools/commons'; +import { parser } from '@aws-lambda-powertools/parser'; +import { z } from 'zod'; + +const orderItemSchema = z.object({ + id: z.number().positive(), + quantity: z.number(), + description: z.string(), +}); + +const orderSchema = z.object({ + id: z.number().positive(), + description: z.string(), + items: z.array(orderItemSchema), + optionalField: z.string().optional(), +}); + +type Order = z.infer; + +class Lambda extends LambdaInterface { + @parser({ schema: orderSchema }) + public async handler(event: Order, _context: Context): Promise { + for (const item of event.items) { + // item is parsed as OrderItem + console.log(item.id); + } + } +} + +export const myFunction = new Lambda(); +export const handler = myFunction.handler.bind(myFunction); diff --git a/docs/snippets/parser/envelopeDecorator.ts b/docs/snippets/parser/envelopeDecorator.ts new file mode 100644 index 0000000000..3563c09f49 --- /dev/null +++ b/docs/snippets/parser/envelopeDecorator.ts @@ -0,0 +1,34 @@ +import { Context } from 'aws-lambda'; +import { LambdaInterface } from '@aws-lambda-powertools/commons'; +import { parser } from '@aws-lambda-powertools/parser'; +import { z } from 'zod'; +import { eventBridgeEnvelope } from '@aws-lambda-powertools/parser/envelopes'; + +const orderItemSchema = z.object({ + id: z.number().positive(), + quantity: z.number(), + description: z.string(), +}); + +const orderSchema = z.object({ + id: z.number().positive(), + description: z.string(), + items: z.array(orderItemSchema), + optionalField: z.string().optional(), +}); + +type Order = z.infer; + +class Lambda extends LambdaInterface { + @parser({ schema: orderSchema, envelope: eventBridgeEnvelope }) // (1) + public async handler(event: Order, _context: Context): Promise { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + for (const item of event.items) { + // item is parsed as OrderItem (2) + console.log(item.id); + } + } +} + +export const myFunction = new Lambda(); +export const handler = myFunction.handler.bind(myFunction); diff --git a/docs/snippets/parser/envelopeMiddy.ts b/docs/snippets/parser/envelopeMiddy.ts new file mode 100644 index 0000000000..e56b3a8950 --- /dev/null +++ b/docs/snippets/parser/envelopeMiddy.ts @@ -0,0 +1,34 @@ +import { Context } from 'aws-lambda'; +import { parser } from '@aws-lambda-powertools/parser/middleware'; +import { z } from 'zod'; +import middy from '@middy/core'; +import { eventBridgeEnvelope } from '@aws-lambda-powertools/parser/envelopes'; + +const orderItemSchema = z.object({ + id: z.number().positive(), + quantity: z.number(), + description: z.string(), +}); + +const orderSchema = z.object({ + id: z.number().positive(), + description: z.string(), + items: z.array(orderItemSchema), + optionalField: z.string().optional(), +}); + +type Order = z.infer; + +const lambdaHandler = async ( + event: Order, + _context: Context +): Promise => { + for (const item of event.items) { + // item is parsed as OrderItem + console.log(item.id); + } +}; + +export const handler = middy(lambdaHandler).use( + parser({ schema: orderSchema, envelope: eventBridgeEnvelope }) +); diff --git a/docs/snippets/parser/examplePayload.json b/docs/snippets/parser/examplePayload.json new file mode 100644 index 0000000000..225be75a69 --- /dev/null +++ b/docs/snippets/parser/examplePayload.json @@ -0,0 +1,21 @@ +{ + "version": "0", + "id": "6a7e8feb-b491-4cf7-a9f1-bf3703467718", + "detail-type": "OrderPurchased", + "source": "OrderService", + "account": "111122223333", + "time": "2020-10-22T18:43:48Z", + "region": "us-west-1", + "resources": ["some_additional"], + "detail": { + "id": 10876546789, + "description": "My order", + "items": [ + { + "id": 1015938732, + "quantity": 1, + "description": "item xpto" + } + ] + } +} diff --git a/docs/snippets/parser/extend.ts b/docs/snippets/parser/extend.ts new file mode 100644 index 0000000000..80288a4350 --- /dev/null +++ b/docs/snippets/parser/extend.ts @@ -0,0 +1,38 @@ +import { Context } from 'aws-lambda'; +import { LambdaInterface } from '@aws-lambda-powertools/commons'; +import { parser } from '@aws-lambda-powertools/parser'; +import { z } from 'zod'; +import { EventBridgeSchema } from '@aws-lambda-powertools/parser/schemas'; + +const orderItemSchema = z.object({ + id: z.number().positive(), + quantity: z.number(), + description: z.string(), +}); + +const orderSchema = z.object({ + id: z.number().positive(), + description: z.string(), + items: z.array(orderItemSchema), + optionalField: z.string().optional(), +}); + +const orderEventSchema = EventBridgeSchema.extend({ + // (1) + detail: orderSchema, +}); + +type OrderEvent = z.infer; + +class Lambda extends LambdaInterface { + @parser({ schema: orderEventSchema }) // (2) + public async handler(event: OrderEvent, _context: Context): Promise { + for (const item of event.detail.items) { + // process OrderItem // (3) + console.log(item); + } + } +} + +export const myFunction = new Lambda(); +export const handler = myFunction.handler.bind(myFunction); diff --git a/docs/snippets/parser/manual.ts b/docs/snippets/parser/manual.ts new file mode 100644 index 0000000000..a5997dc1f2 --- /dev/null +++ b/docs/snippets/parser/manual.ts @@ -0,0 +1,30 @@ +import { Context, EventBridgeEvent } from 'aws-lambda'; +import { z } from 'zod'; +import { eventBridgeEnvelope } from '@aws-lambda-powertools/parser/envelopes'; +import { EventBridgeSchema } from '@aws-lambda-powertools/parser/schemas'; + +const orderItemSchema = z.object({ + id: z.number().positive(), + quantity: z.number(), + description: z.string(), +}); + +const orderSchema = z.object({ + id: z.number().positive(), + description: z.string(), + items: z.array(orderItemSchema), + optionalField: z.string().optional(), +}); + +type Order = z.infer; + +export const handler = async ( + event: EventBridgeEvent, + _context: Context +): Promise => { + const parsed = EventBridgeSchema.parse(event); // (1) + console.log(parsed); + + const orders: Order[] = eventBridgeEnvelope(event, orderSchema); // (2) + console.log(orders); +}; diff --git a/docs/snippets/parser/middy.ts b/docs/snippets/parser/middy.ts new file mode 100644 index 0000000000..f95e3ac35f --- /dev/null +++ b/docs/snippets/parser/middy.ts @@ -0,0 +1,33 @@ +import { Context } from 'aws-lambda'; +import { parser } from '@aws-lambda-powertools/parser/middleware'; +import { z } from 'zod'; +import middy from '@middy/core'; + +const orderItemSchema = z.object({ + id: z.number().positive(), + quantity: z.number(), + description: z.string(), +}); + +const orderSchema = z.object({ + id: z.number().positive(), + description: z.string(), + items: z.array(orderItemSchema), + optionalField: z.string().optional(), +}); + +type Order = z.infer; + +const lambdaHandler = async ( + event: Order, + _context: Context +): Promise => { + for (const item of event.items) { + // item is parsed as OrderItem + console.log(item.id); + } +}; + +export const handler = middy(lambdaHandler).use( + parser({ schema: orderSchema }) +); diff --git a/docs/snippets/parser/schema.ts b/docs/snippets/parser/schema.ts new file mode 100644 index 0000000000..138e375239 --- /dev/null +++ b/docs/snippets/parser/schema.ts @@ -0,0 +1,16 @@ +import { z } from 'zod'; + +const orderItemSchema = z.object({ + id: z.number().positive(), + quantity: z.number(), + description: z.string(), +}); + +const orderSchema = z.object({ + id: z.number().positive(), + description: z.string(), + items: z.array(orderItemSchema), + optionalField: z.string().optional(), +}); + +export { orderSchema, orderItemSchema }; diff --git a/docs/snippets/tsconfig.json b/docs/snippets/tsconfig.json index 1a3fe8b171..8cbaa1ae28 100644 --- a/docs/snippets/tsconfig.json +++ b/docs/snippets/tsconfig.json @@ -4,6 +4,8 @@ "rootDir": "./", "baseUrl": ".", "noEmit": true, + "noUnusedLocals": false, + "allowUnusedLabels": true, "paths": { "@aws-lambda-powertools/parameters/ssm": [ "../../packages/parameters/lib/ssm" diff --git a/docs/utilities/parser.md b/docs/utilities/parser.md new file mode 100644 index 0000000000..f63cd8a585 --- /dev/null +++ b/docs/utilities/parser.md @@ -0,0 +1,180 @@ +--- +title: Parser (zod) +descrition: Utility +--- + +This utility provides data validation and parsing using [zod](https://zod.dev). + +## Key features + +* Define data schema as zod schema, then parse, validate and extract only what you want +* Built-in envelopes to unwrap and validate popular event sources payloads +* Extend and customize envelopes to fit your needs +* Available for middy middleware and TypeScript method decorators + +## Getting started + +### Install + +```bash +npm install @aws-lambda-powertools/parser zod +``` + +This utility supports zod v3.0.0 and above. + +## Define schema + +You can define your schema using zod: + +```typescript +--8<-- "docs/snippets/parser/schema.ts" +``` + +This is a schema for order and oder items using zod. +You can create more complex schemas using zod, such as nested objects, arrays, unions, etc. see [zod documentation](https://zod.dev) for more details. + +## Parse events + +You can parse inbound events using `parser` decorator or middy middleware. +Both are also able to parse either an object or JSON string as an input. + +???+ note + The decorator and middleware will replace the event object with the parsed schema if successful. This means you might be careful when nesting other decorators that expect event to have a specific structure. + +=== "Middy middleware" + ```typescript hl_lines="31" + --8<-- "docs/snippets/parser/middy.ts" + ``` + +=== "Decorator" + ```typescript hl_lines="22" + --8<-- "docs/snippets/parser/decorator.ts" + ``` + +## Built-in schemas + + +Parser comes with the following built-in schemas: + +| Model name | Description | +|-----------------------------------------------| ------------------------------------------------------------------------------------- | +| **AlbSchema** | Lambda Event Source payload for Amazon Application Load Balancer | +| **APIGatewayProxyEventSchema** | Lambda Event Source payload for Amazon API Gateway | +| **APIGatewayProxyEventV2Schema** | Lambda Event Source payload for Amazon API Gateway v2 payload | +| **BedrockAgentEventSchema** | Lambda Event Source payload for Bedrock Agents | +| **CloudFormationCustomResourceCreateSchema** | Lambda Event Source payload for AWS CloudFormation `CREATE` operation | +| **CloudFormationCustomResourceUpdateSchema** | Lambda Event Source payload for AWS CloudFormation `UPDATE` operation | +| **CloudFormationCustomResourceDeleteSchema** | Lambda Event Source payload for AWS CloudFormation `DELETE` operation | +| **CloudwatchLogsSchema** | Lambda Event Source payload for Amazon CloudWatch Logs | +| **DynamoDBStreamSchema** | Lambda Event Source payload for Amazon DynamoDB Streams | +| **EventBridgeSchema** | Lambda Event Source payload for Amazon EventBridge | +| **KafkaMskEventSchema** | Lambda Event Source payload for AWS MSK payload | +| **KafkaSelfManagedEventSchema** | Lambda Event Source payload for self managed Kafka payload | +| **KinesisDataStreamSchema** | Lambda Event Source payload for Amazon Kinesis Data Streams | +| **KinesisFirehoseSchema** | Lambda Event Source payload for Amazon Kinesis Firehose | +| **KinesisFirehoseSqsSchema** | Lambda Event Source payload for SQS messages wrapped in Kinesis Firehose records | +| **LambdaFunctionUrlSchema** | Lambda Event Source payload for Lambda Function URL payload | +| **S3EventNotificationEventBridgeSchema** | Lambda Event Source payload for Amazon S3 Event Notification to EventBridge. | +| **S3Schema** | Lambda Event Source payload for Amazon S3 | +| **S3ObjectLambdaEvent** | Lambda Event Source payload for Amazon S3 Object Lambda | +| **S3SqsEventNotificationSchema** | Lambda Event Source payload for S3 event notifications wrapped in SQS event (S3->SQS) | +| **SesSchema** | Lambda Event Source payload for Amazon Simple Email Service | +| **SnsSchema** | Lambda Event Source payload for Amazon Simple Notification Service | +| **SqsSchema** | Lambda Event Source payload for Amazon SQS | +| **VpcLatticeSchema** | Lambda Event Source payload for Amazon VPC Lattice | +| **VpcLatticeV2Schema** | Lambda Event Source payload for Amazon VPC Lattice v2 payload | + +### Extend built-in schemas + +You can extend them to include your own schema, and yet have all other known fields parsed along the way. + +=== "handler.ts" + ```typescript hl_lines="20-22 27 30" + --8<-- "docs/snippets/parser/extend.ts" + ``` + + 1. Extend built-in `EventBridgeSchema` with your own detail schema + 2. Pass the extended schema to `parser` decorator or middy middleware + 3. `event` is validated including your custom schema and now available in your handler + + +=== "Example payload" + + ```json + --8<-- "docs/snippets/parser/examplePayload.json" + ``` + + + +## Envelopes + +When trying to parse your payloads wrapped in a known structure, you might encounter the following situations: + +* Your actual payload is wrapped around a known structure, for example Lambda Event Sources like EventBridge +* You're only interested in a portion of the payload, for example parsing the detail of custom events in EventBridge, or body of SQS records +* You can either solve these situations by creating a schema of these known structures, parsing them, then extracting and parsing a key where your payload is. + +This can become difficult quite quickly. Parser simplifies the development through a feature named Envelope. +Envelopes can be used via envelope parameter available in both parse function and `parser` decorator. +Here's an example of parsing a schema found in an event coming from EventBridge, where all you want is what's inside the detail key. + +=== "Decorator" + ```typescript hl_lines="5 23" + --8<-- "docs/snippets/parser/envelopeDecorator.ts" + ``` + + 1. Pass `eventBridgeEnvelope` to `parser` decorator + 2. `event` is parsed and replaced as `Order` object + +=== "Middy middleware" + ```typescript hl_lines="5 32" + --8<-- "docs/snippets/parser/envelopeMiddy.ts" + ``` + +The envelopes are functions that take an event and the schema to parse, and return the result of the inner schema. +Depending on the envelope it can be something simple like extracting a key. +We have also complex envelopes that parse the payload from a string, decode base64, uncompress gzip, etc. + +### Built-in envelopes + +Parser comes with the following built-in envelopes: + +| Envelope name | Behaviour | +| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **apiGatewayEnvelope** | 1. Parses data using `APIGatewayProxyEventSchema`.
2. Parses `body` key using your schema and returns it. | +| **apiGatewayV2Envelope** | 1. Parses data using `APIGatewayProxyEventV2Schema`.
2. Parses `body` key using your schema and returns it. | +| **cloudWatchEnvelope** | 1. Parses data using `CloudwatchLogsSchema` which will base64 decode and decompress it.
2. Parses records in `message` key using your schema and return them in a list. | +| **dynamoDBStreamEnvelope** | 1. Parses data using `DynamoDBStreamSchema`.
2. Parses records in `NewImage` and `OldImage` keys using your schema.
3. Returns a list with a dictionary containing `NewImage` and `OldImage` keys | +| **eventBridgeEnvelope** | 1. Parses data using `EventBridgeSchema`.
2. Parses `detail` key using your schema and returns it. | +| **kafkaEnvelope** | 1. Parses data using `KafkaRecordSchema`.
2. Parses `value` key using your schema and returns it. | +| **kinesisEnvelope** | 1. Parses data using `KinesisDataStreamSchema` which will base64 decode it.
2. Parses records in `Records` key using your schema and returns them in a list. | +| **kinesisFirehoseEnvelope** | 1. Parses data using `KinesisFirehoseSchema` which will base64 decode it.
2. Parses records in `Records` key using your schema and returns them in a list. | +| **lambdaFunctionUrlEnvelope** | 1. Parses data using `LambdaFunctionUrlSchema`.
2. Parses `body` key using your schema and returns it. | +| **snsEnvelope** | 1. Parses data using `SnsSchema`.
2. Parses records in `body` key using your schema and return them in a list. | +| **snsSqsEnvelope** | 1. Parses data using `SqsSchema`.
2. Parses SNS records in `body` key using `SnsNotificationSchema`.
3. Parses data in `Message` key using your schema and return them in a list. | +| **sqsEnvelope** | 1. Parses data using `SqsSchema`.
2. Parses records in `body` key using your schema and return them in a list. | +| **vpcLatticeEnvelope** | 1. Parses data using `VpcLatticeSchema`.
2. Parses `value` key using your schema and returns it. | +| **vpcLatticeV2Envelope** | 1. Parses data using `VpcLatticeSchema`.
2. Parses `value` key using your schema and returns it. | + + +## Manual parsing + +You can use built-in envelopes and schemas to parse the incoming events manually: + +```typescript +--8<-- "docs/snippets/parser/manual.ts" +``` +1. Use `SqsSchema` to parse the event, the `Records` will be parsed as string. You have to parse the records manually + + +## Types + + + +## FAQs + + + + + + diff --git a/mkdocs.yml b/mkdocs.yml index 4719889feb..a718ef0b15 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -19,6 +19,7 @@ nav: - utilities/parameters.md - utilities/idempotency.md - utilities/batch.md + - utilities/parser.md - Processes: - Roadmap: roadmap.md - Maintainers: maintainers.md diff --git a/packages/parser/package.json b/packages/parser/package.json index fb4b54fe51..fe89ba9c5c 100644 --- a/packages/parser/package.json +++ b/packages/parser/package.json @@ -37,6 +37,18 @@ "types": "./lib/esm/index.d.ts", "default": "./lib/esm/index.js" } + }, + "./middleware": { + "import": "./lib/esm/parser.js", + "require": "./lib/cjs/parser.js" + }, + "./schemas": { + "import": "./lib/esm/index.js", + "require": "./lib/cjs/index.js" + }, + "./envelopes": { + "import": "./lib/esm/index.js", + "require": "./lib/cjs/index.js" } }, "main": "./lib/cjs/index.js", diff --git a/packages/parser/src/envelopes/dynamodb.ts b/packages/parser/src/envelopes/dynamodb.ts index bb378b2d0b..1dca32fb33 100644 --- a/packages/parser/src/envelopes/dynamodb.ts +++ b/packages/parser/src/envelopes/dynamodb.ts @@ -13,7 +13,7 @@ type DynamoDBStreamEnvelopeResponse = { * Note: Values are the parsed models. Images' values can also be None, and * length of the list is the record's amount in the original event. */ -export const dynamoDDStreamEnvelope = ( +export const dynamoDBStreamEnvelope = ( data: unknown, schema: T ): DynamoDBStreamEnvelopeResponse[] => { diff --git a/packages/parser/src/envelopes/index.ts b/packages/parser/src/envelopes/index.ts new file mode 100644 index 0000000000..0ff3615920 --- /dev/null +++ b/packages/parser/src/envelopes/index.ts @@ -0,0 +1,13 @@ +export { apiGatewayEnvelope } from './apigw.js'; +export { apiGatewayV2Envelope } from './apigwv2.js'; +export { cloudWatchEnvelope } from './cloudwatch.js'; +export { dynamoDBStreamEnvelope } from './dynamodb.js'; +export { eventBridgeEnvelope } from './event-bridge.js'; +export { kafkaEnvelope } from './kafka.js'; +export { kinesisEnvelope } from './kinesis.js'; +export { kinesisFirehoseEnvelope } from './kinesis-firehose.js'; +export { lambdaFunctionUrlEnvelope } from './lambda.js'; +export { snsEnvelope, snsSqsEnvelope } from './sns.js'; +export { sqsEnvelope } from './sqs.js'; +export { vpcLatticeEnvelope } from './vpc-lattice.js'; +export { vpcLatticeV2Envelope } from './vpc-latticev2.js'; diff --git a/packages/parser/src/index.ts b/packages/parser/src/index.ts index e69de29bb2..bb7ee75eb5 100644 --- a/packages/parser/src/index.ts +++ b/packages/parser/src/index.ts @@ -0,0 +1 @@ +export { parser } from './parser.js'; diff --git a/packages/parser/src/schemas/index.ts b/packages/parser/src/schemas/index.ts new file mode 100644 index 0000000000..0a215038f3 --- /dev/null +++ b/packages/parser/src/schemas/index.ts @@ -0,0 +1,34 @@ +export { AlbSchema, AlbMultiValueHeadersSchema } from './alb.js'; +export { APIGatewayProxyEventSchema } from './apigw.js'; +export { APIGatewayProxyEventV2Schema } from './apigwv2.js'; +export { + CloudFormationCustomResourceBaseSchema, + CloudFormationCustomResourceCreateSchema, + CloudFormationCustomResourceDeleteSchema, + CloudFormationCustomResourceUpdateSchema, +} from './cloudformation-custom-resource.js'; +export { + CloudWatchLogsSchema, + CloudWatchLogEventSchema, + CloudWatchLogsDecodeSchema, +} from './cloudwatch.js'; +export { DynamoDBStreamSchema } from './dynamodb.js'; +export { EventBridgeSchema } from './eventbridge.js'; +export { KafkaMskEventSchema, KafkaSelfManagedEventSchema } from './kafka.js'; +export { KinesisDataStreamSchema } from './kinesis.js'; +export { + KinesisFirehoseSchema, + KinesisFirehoseSqsSchema, +} from './kinesis-firehose.js'; +export { LambdaFunctionUrlSchema } from './lambda.js'; +export { + S3Schema, + S3EventNotificationEventBridgeSchema, + S3SqsEventNotificationSchema, + S3ObjectLambdaEventSchema, +} from './s3.js'; +export { SnsSchema } from './sns.js'; +export { SqsSchema } from './sqs.js'; +export { SesSchema } from './ses.js'; +export { VpcLatticeSchema } from './vpc-lattice.js'; +export { VpcLatticeV2Schema } from './vpc-latticev2.js'; diff --git a/packages/parser/src/types/envelope.ts b/packages/parser/src/types/envelope.ts index e54958dca2..c53f8893c8 100644 --- a/packages/parser/src/types/envelope.ts +++ b/packages/parser/src/types/envelope.ts @@ -1,7 +1,7 @@ import { type apiGatewayEnvelope } from '../envelopes/apigw.js'; import { type apiGatewayV2Envelope } from '../envelopes/apigwv2.js'; import { type cloudWatchEnvelope } from '../envelopes/cloudwatch.js'; -import { type dynamoDDStreamEnvelope } from '../envelopes/dynamodb.js'; +import { type dynamoDBStreamEnvelope } from '../envelopes/dynamodb.js'; import { type kafkaEnvelope } from '../envelopes/kafka.js'; import { type kinesisEnvelope } from '../envelopes/kinesis.js'; import { type kinesisFirehoseEnvelope } from '../envelopes/kinesis-firehose.js'; @@ -16,7 +16,7 @@ export type Envelope = | typeof apiGatewayEnvelope | typeof apiGatewayV2Envelope | typeof cloudWatchEnvelope - | typeof dynamoDDStreamEnvelope + | typeof dynamoDBStreamEnvelope | typeof eventBridgeEnvelope | typeof kafkaEnvelope | typeof kinesisEnvelope diff --git a/packages/parser/tests/unit/envelopes/dynamodb.test.ts b/packages/parser/tests/unit/envelopes/dynamodb.test.ts index 342ad474e3..c87899f749 100644 --- a/packages/parser/tests/unit/envelopes/dynamodb.test.ts +++ b/packages/parser/tests/unit/envelopes/dynamodb.test.ts @@ -8,7 +8,7 @@ import { generateMock } from '@anatine/zod-mock'; import { TestEvents } from '../schema/utils.js'; import { DynamoDBStreamEvent } from 'aws-lambda'; import { z } from 'zod'; -import { dynamoDDStreamEnvelope } from '../../../src/envelopes/dynamodb'; +import { dynamoDBStreamEnvelope } from '../../../src/envelopes/dynamodb'; describe('DynamoDB', () => { const schema = z.object({ @@ -30,7 +30,7 @@ describe('DynamoDB', () => { (dynamodbEvent.Records[1].dynamodb!.OldImage as typeof mockOldImage) = mockOldImage; - const parsed = dynamoDDStreamEnvelope(dynamodbEvent, schema); + const parsed = dynamoDBStreamEnvelope(dynamodbEvent, schema); expect(parsed[0]).toEqual({ OldImage: mockOldImage, NewImage: mockNewImage, From a67698838c73560b809b64b9a2c8add52a250fd3 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Thu, 4 Jan 2024 06:13:17 +0100 Subject: [PATCH 02/23] fix test imports --- packages/parser/tests/unit/envelopes/apigwt.test.ts | 2 +- packages/parser/tests/unit/envelopes/apigwv2.test.ts | 2 +- packages/parser/tests/unit/envelopes/cloudwatch.test.ts | 4 ++-- packages/parser/tests/unit/envelopes/dynamodb.test.ts | 2 +- packages/parser/tests/unit/envelopes/eventbridge.test.ts | 2 +- packages/parser/tests/unit/envelopes/kafka.test.ts | 2 +- .../parser/tests/unit/envelopes/kinesis-firehose.test.ts | 4 ++-- packages/parser/tests/unit/envelopes/kinesis.test.ts | 2 +- packages/parser/tests/unit/envelopes/lambda.test.ts | 2 +- packages/parser/tests/unit/envelopes/sns.test.ts | 2 +- packages/parser/tests/unit/envelopes/sqs.test.ts | 2 +- packages/parser/tests/unit/envelopes/vpc-lattice.test.ts | 4 ++-- packages/parser/tests/unit/envelopes/vpc-latticev2.test.ts | 4 ++-- packages/parser/tests/unit/parser.decorator.test.ts | 6 +++--- packages/parser/tests/unit/parser.middy.test.ts | 4 ++-- packages/parser/tests/unit/schema/alb.test.ts | 5 +---- packages/parser/tests/unit/schema/apigw.test.ts | 2 +- packages/parser/tests/unit/schema/apigwv2.test.ts | 2 +- .../unit/schema/cloudformation-custom-resource.test.ts | 2 +- packages/parser/tests/unit/schema/cloudwatch.test.ts | 2 +- packages/parser/tests/unit/schema/dynamodb.test.ts | 2 +- packages/parser/tests/unit/schema/eventbridge.test.ts | 2 +- packages/parser/tests/unit/schema/kafka.test.ts | 2 +- packages/parser/tests/unit/schema/kinesis.test.ts | 4 ++-- packages/parser/tests/unit/schema/lambda.test.ts | 2 +- packages/parser/tests/unit/schema/s3.test.ts | 2 +- packages/parser/tests/unit/schema/ses.test.ts | 2 +- packages/parser/tests/unit/schema/sns.test.ts | 2 +- packages/parser/tests/unit/schema/sqs.test.ts | 2 +- packages/parser/tests/unit/schema/vpc-lattice.test.ts | 2 +- packages/parser/tests/unit/schema/vpc-latticev2.test.ts | 2 +- 31 files changed, 39 insertions(+), 42 deletions(-) diff --git a/packages/parser/tests/unit/envelopes/apigwt.test.ts b/packages/parser/tests/unit/envelopes/apigwt.test.ts index 6c51736b16..bed8445310 100644 --- a/packages/parser/tests/unit/envelopes/apigwt.test.ts +++ b/packages/parser/tests/unit/envelopes/apigwt.test.ts @@ -7,7 +7,7 @@ import { generateMock } from '@anatine/zod-mock'; import { TestEvents, TestSchema } from '../schema/utils.js'; import { ApiGatewayProxyEvent } from '../../../src/types/schema.js'; -import { apiGatewayEnvelope } from '../../../src/envelopes/apigw'; +import { apiGatewayEnvelope } from '../../../src/envelopes'; describe('ApigwEnvelope ', () => { it('should parse custom schema in envelope', () => { diff --git a/packages/parser/tests/unit/envelopes/apigwv2.test.ts b/packages/parser/tests/unit/envelopes/apigwv2.test.ts index acf7ee815b..5b2ec240fd 100644 --- a/packages/parser/tests/unit/envelopes/apigwv2.test.ts +++ b/packages/parser/tests/unit/envelopes/apigwv2.test.ts @@ -7,7 +7,7 @@ import { TestEvents, TestSchema } from '../schema/utils.js'; import { generateMock } from '@anatine/zod-mock'; import { APIGatewayProxyEventV2 } from 'aws-lambda'; -import { apiGatewayV2Envelope } from '../../../src/envelopes/apigwv2'; +import { apiGatewayV2Envelope } from '../../../src/envelopes'; describe('ApiGwV2Envelope ', () => { it('should parse custom schema in envelope', () => { diff --git a/packages/parser/tests/unit/envelopes/cloudwatch.test.ts b/packages/parser/tests/unit/envelopes/cloudwatch.test.ts index 3258768b5a..4c238bac48 100644 --- a/packages/parser/tests/unit/envelopes/cloudwatch.test.ts +++ b/packages/parser/tests/unit/envelopes/cloudwatch.test.ts @@ -9,9 +9,9 @@ import { gzipSync } from 'node:zlib'; import { CloudWatchLogEventSchema, CloudWatchLogsDecodeSchema, -} from '../../../src/schemas/cloudwatch.js'; +} from '../../../src/schemas'; import { TestSchema } from '../schema/utils.js'; -import { cloudWatchEnvelope } from '../../../src/envelopes/cloudwatch'; +import { cloudWatchEnvelope } from '../../../src/envelopes'; describe('CloudWatch', () => { it('should parse custom schema in envelope', () => { diff --git a/packages/parser/tests/unit/envelopes/dynamodb.test.ts b/packages/parser/tests/unit/envelopes/dynamodb.test.ts index c87899f749..01814153a1 100644 --- a/packages/parser/tests/unit/envelopes/dynamodb.test.ts +++ b/packages/parser/tests/unit/envelopes/dynamodb.test.ts @@ -8,7 +8,7 @@ import { generateMock } from '@anatine/zod-mock'; import { TestEvents } from '../schema/utils.js'; import { DynamoDBStreamEvent } from 'aws-lambda'; import { z } from 'zod'; -import { dynamoDBStreamEnvelope } from '../../../src/envelopes/dynamodb'; +import { dynamoDBStreamEnvelope } from '../../../src/envelopes'; describe('DynamoDB', () => { const schema = z.object({ diff --git a/packages/parser/tests/unit/envelopes/eventbridge.test.ts b/packages/parser/tests/unit/envelopes/eventbridge.test.ts index 8212e77d9f..5f5281caa5 100644 --- a/packages/parser/tests/unit/envelopes/eventbridge.test.ts +++ b/packages/parser/tests/unit/envelopes/eventbridge.test.ts @@ -7,7 +7,7 @@ import { TestEvents, TestSchema } from '../schema/utils.js'; import { generateMock } from '@anatine/zod-mock'; import { EventBridgeEvent } from 'aws-lambda'; -import { eventBridgeEnvelope } from '../../../src/envelopes/event-bridge.js'; +import { eventBridgeEnvelope } from '../../../src/envelopes'; describe('EventBridgeEnvelope ', () => { it('should parse eventbridge event', () => { diff --git a/packages/parser/tests/unit/envelopes/kafka.test.ts b/packages/parser/tests/unit/envelopes/kafka.test.ts index 57e43a584f..509c333b4c 100644 --- a/packages/parser/tests/unit/envelopes/kafka.test.ts +++ b/packages/parser/tests/unit/envelopes/kafka.test.ts @@ -7,7 +7,7 @@ import { generateMock } from '@anatine/zod-mock'; import { TestEvents, TestSchema } from '../schema/utils.js'; import { MSKEvent, SelfManagedKafkaEvent } from 'aws-lambda'; -import { kafkaEnvelope } from '../../../src/envelopes/kafka'; +import { kafkaEnvelope } from '../../../src/envelopes'; describe('Kafka', () => { it('should parse MSK kafka envelope', () => { diff --git a/packages/parser/tests/unit/envelopes/kinesis-firehose.test.ts b/packages/parser/tests/unit/envelopes/kinesis-firehose.test.ts index 581785d99f..7983fd3ae3 100644 --- a/packages/parser/tests/unit/envelopes/kinesis-firehose.test.ts +++ b/packages/parser/tests/unit/envelopes/kinesis-firehose.test.ts @@ -6,9 +6,9 @@ import { TestEvents, TestSchema } from '../schema/utils.js'; import { generateMock } from '@anatine/zod-mock'; -import { KinesisFirehoseSchema } from '../../../src/schemas/kinesis-firehose.js'; +import { KinesisFirehoseSchema } from '../../../src/schemas'; import { z } from 'zod'; -import { kinesisFirehoseEnvelope } from '../../../src/envelopes/kinesis-firehose'; +import { kinesisFirehoseEnvelope } from '../../../src/envelopes'; describe('Kinesis Firehose Envelope', () => { it('should parse records for PutEvent', () => { diff --git a/packages/parser/tests/unit/envelopes/kinesis.test.ts b/packages/parser/tests/unit/envelopes/kinesis.test.ts index 6395cf9803..ed116e24a3 100644 --- a/packages/parser/tests/unit/envelopes/kinesis.test.ts +++ b/packages/parser/tests/unit/envelopes/kinesis.test.ts @@ -7,7 +7,7 @@ import { generateMock } from '@anatine/zod-mock'; import { KinesisStreamEvent } from 'aws-lambda'; import { TestEvents, TestSchema } from '../schema/utils.js'; -import { kinesisEnvelope } from '../../../src/envelopes/kinesis'; +import { kinesisEnvelope } from '../../../src/envelopes'; describe('Kinesis', () => { it('should parse Kinesis Stream event', () => { diff --git a/packages/parser/tests/unit/envelopes/lambda.test.ts b/packages/parser/tests/unit/envelopes/lambda.test.ts index f00411e8b3..b31697cf08 100644 --- a/packages/parser/tests/unit/envelopes/lambda.test.ts +++ b/packages/parser/tests/unit/envelopes/lambda.test.ts @@ -7,7 +7,7 @@ import { TestEvents, TestSchema } from '../schema/utils.js'; import { generateMock } from '@anatine/zod-mock'; import { APIGatewayProxyEventV2 } from 'aws-lambda'; -import { lambdaFunctionUrlEnvelope } from '../../../src/envelopes/lambda'; +import { lambdaFunctionUrlEnvelope } from '../../../src/envelopes'; describe('Lambda Functions Url ', () => { it('should parse custom schema in envelope', () => { diff --git a/packages/parser/tests/unit/envelopes/sns.test.ts b/packages/parser/tests/unit/envelopes/sns.test.ts index 3a380303ed..217ec29c92 100644 --- a/packages/parser/tests/unit/envelopes/sns.test.ts +++ b/packages/parser/tests/unit/envelopes/sns.test.ts @@ -8,7 +8,7 @@ import { z } from 'zod'; import { generateMock } from '@anatine/zod-mock'; import { SNSEvent, SQSEvent } from 'aws-lambda'; import { TestEvents, TestSchema } from '../schema/utils.js'; -import { snsEnvelope, snsSqsEnvelope } from '../../../src/envelopes/sns'; +import { snsEnvelope, snsSqsEnvelope } from '../../../src/envelopes'; describe('SNS Envelope', () => { it('should parse custom schema in envelope', () => { diff --git a/packages/parser/tests/unit/envelopes/sqs.test.ts b/packages/parser/tests/unit/envelopes/sqs.test.ts index 4fb775433f..041904ebc1 100644 --- a/packages/parser/tests/unit/envelopes/sqs.test.ts +++ b/packages/parser/tests/unit/envelopes/sqs.test.ts @@ -7,7 +7,7 @@ import { generateMock } from '@anatine/zod-mock'; import { TestEvents, TestSchema } from '../schema/utils.js'; import { SQSEvent } from 'aws-lambda'; -import { sqsEnvelope } from '../../../src/envelopes/sqs'; +import { sqsEnvelope } from '../../../src/envelopes'; describe('SqsEnvelope ', () => { it('should parse custom schema in envelope', () => { diff --git a/packages/parser/tests/unit/envelopes/vpc-lattice.test.ts b/packages/parser/tests/unit/envelopes/vpc-lattice.test.ts index a3b1b0f6c4..23af974009 100644 --- a/packages/parser/tests/unit/envelopes/vpc-lattice.test.ts +++ b/packages/parser/tests/unit/envelopes/vpc-lattice.test.ts @@ -6,9 +6,9 @@ import { generateMock } from '@anatine/zod-mock'; import { TestEvents, TestSchema } from '../schema/utils.js'; -import { VpcLatticeSchema } from '../../../src/schemas/vpc-lattice.js'; +import { VpcLatticeSchema } from '../../../src/schemas'; import { z } from 'zod'; -import { vpcLatticeEnvelope } from '../../../src/envelopes/vpc-lattice'; +import { vpcLatticeEnvelope } from '../../../src/envelopes'; describe('VPC Lattice envelope', () => { it('should parse VPC Lattice event', () => { diff --git a/packages/parser/tests/unit/envelopes/vpc-latticev2.test.ts b/packages/parser/tests/unit/envelopes/vpc-latticev2.test.ts index 207dedb2da..bc260f197b 100644 --- a/packages/parser/tests/unit/envelopes/vpc-latticev2.test.ts +++ b/packages/parser/tests/unit/envelopes/vpc-latticev2.test.ts @@ -5,10 +5,10 @@ */ import { generateMock } from '@anatine/zod-mock'; -import { VpcLatticeSchema } from '../../../src/schemas/vpc-lattice.js'; +import { VpcLatticeSchema } from '../../../src/schemas'; import { z } from 'zod'; import { TestEvents, TestSchema } from '../schema/utils.js'; -import { vpcLatticeV2Envelope } from '../../../src/envelopes/vpc-latticev2'; +import { vpcLatticeV2Envelope } from '../../../src/envelopes'; describe('VPC Lattice envelope', () => { it('should parse VPC Lattice event', () => { diff --git a/packages/parser/tests/unit/parser.decorator.test.ts b/packages/parser/tests/unit/parser.decorator.test.ts index eba2a3b59b..7e4d7e9aa6 100644 --- a/packages/parser/tests/unit/parser.decorator.test.ts +++ b/packages/parser/tests/unit/parser.decorator.test.ts @@ -6,11 +6,11 @@ import { LambdaInterface } from '@aws-lambda-powertools/commons/lib/esm/types'; import { Context, EventBridgeEvent } from 'aws-lambda'; -import { parser } from '../../src/parser'; +import { parser } from '../../src'; import { TestSchema, TestEvents } from './schema/utils'; import { generateMock } from '@anatine/zod-mock'; -import { eventBridgeEnvelope } from '../../src/envelopes/event-bridge'; -import { EventBridgeSchema } from '../../src/schemas/eventbridge'; +import { eventBridgeEnvelope } from '../../src/envelopes'; +import { EventBridgeSchema } from '../../src/schemas'; import { z } from 'zod'; describe('Parser Decorator', () => { diff --git a/packages/parser/tests/unit/parser.middy.test.ts b/packages/parser/tests/unit/parser.middy.test.ts index 979892a21c..0e53c4d5ea 100644 --- a/packages/parser/tests/unit/parser.middy.test.ts +++ b/packages/parser/tests/unit/parser.middy.test.ts @@ -8,9 +8,9 @@ import middy from '@middy/core'; import { Context } from 'aws-lambda'; import { parser } from '../../src/middleware/parser.js'; import { generateMock } from '@anatine/zod-mock'; -import { SqsSchema } from '../../src/schemas/sqs.js'; +import { SqsSchema } from '../../src/schemas'; import { z, type ZodSchema } from 'zod'; -import { sqsEnvelope } from '../../src/envelopes/sqs'; +import { sqsEnvelope } from '../../src/envelopes'; import { TestSchema } from './schema/utils'; describe('Middleware: parser', () => { diff --git a/packages/parser/tests/unit/schema/alb.test.ts b/packages/parser/tests/unit/schema/alb.test.ts index 071f4598ce..3c39b7f734 100644 --- a/packages/parser/tests/unit/schema/alb.test.ts +++ b/packages/parser/tests/unit/schema/alb.test.ts @@ -3,10 +3,7 @@ * * @group unit/parser/schema/ */ -import { - AlbSchema, - AlbMultiValueHeadersSchema, -} from '../../../src/schemas/alb.js'; +import { AlbSchema, AlbMultiValueHeadersSchema } from '../../../src/schemas'; import { TestEvents } from './utils.js'; describe('ALB ', () => { diff --git a/packages/parser/tests/unit/schema/apigw.test.ts b/packages/parser/tests/unit/schema/apigw.test.ts index 472aa89d39..8b03c9ffbe 100644 --- a/packages/parser/tests/unit/schema/apigw.test.ts +++ b/packages/parser/tests/unit/schema/apigw.test.ts @@ -4,7 +4,7 @@ * @group unit/parser/schema/ */ -import { APIGatewayProxyEventSchema } from '../../../src/schemas/apigw.js'; +import { APIGatewayProxyEventSchema } from '../../../src/schemas/'; import { TestEvents } from './utils.js'; describe('APIGateway ', () => { diff --git a/packages/parser/tests/unit/schema/apigwv2.test.ts b/packages/parser/tests/unit/schema/apigwv2.test.ts index 59faa6ca70..1a6b1f9670 100644 --- a/packages/parser/tests/unit/schema/apigwv2.test.ts +++ b/packages/parser/tests/unit/schema/apigwv2.test.ts @@ -4,7 +4,7 @@ * @group unit/parser/schema/ */ -import { APIGatewayProxyEventV2Schema } from '../../../src/schemas/apigwv2.js'; +import { APIGatewayProxyEventV2Schema } from '../../../src/schemas'; import { TestEvents } from './utils.js'; describe('API GW v2 ', () => { diff --git a/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts b/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts index d7ac35ac29..a04c0784b8 100644 --- a/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts +++ b/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts @@ -8,7 +8,7 @@ import { CloudFormationCustomResourceCreateSchema, CloudFormationCustomResourceUpdateSchema, CloudFormationCustomResourceDeleteSchema, -} from '../../../src/schemas/cloudformation-custom-resource.js'; +} from '../../../src/schemas'; import { TestEvents } from './utils.js'; describe('CloudFormationCustomResource ', () => { diff --git a/packages/parser/tests/unit/schema/cloudwatch.test.ts b/packages/parser/tests/unit/schema/cloudwatch.test.ts index c12e0d608c..f212bb6587 100644 --- a/packages/parser/tests/unit/schema/cloudwatch.test.ts +++ b/packages/parser/tests/unit/schema/cloudwatch.test.ts @@ -4,7 +4,7 @@ * @group unit/parser/schema/ */ -import { CloudWatchLogsSchema } from '../../../src/schemas/cloudwatch.js'; +import { CloudWatchLogsSchema } from '../../../src/schemas'; import { TestEvents } from './utils.js'; describe('CloudWatchLogs ', () => { diff --git a/packages/parser/tests/unit/schema/dynamodb.test.ts b/packages/parser/tests/unit/schema/dynamodb.test.ts index 821d484f40..c0de0ff56a 100644 --- a/packages/parser/tests/unit/schema/dynamodb.test.ts +++ b/packages/parser/tests/unit/schema/dynamodb.test.ts @@ -4,7 +4,7 @@ * @group unit/parser/schema/ */ -import { DynamoDBStreamSchema } from '../../../src/schemas/dynamodb.js'; +import { DynamoDBStreamSchema } from '../../../src/schemas'; import { TestEvents } from './utils.js'; describe('DynamoDB ', () => { diff --git a/packages/parser/tests/unit/schema/eventbridge.test.ts b/packages/parser/tests/unit/schema/eventbridge.test.ts index b7ed50d37c..69594f8c66 100644 --- a/packages/parser/tests/unit/schema/eventbridge.test.ts +++ b/packages/parser/tests/unit/schema/eventbridge.test.ts @@ -4,7 +4,7 @@ * @group unit/parser/schema/ */ -import { EventBridgeSchema } from '../../../src/schemas/eventbridge.js'; +import { EventBridgeSchema } from '../../../src/schemas'; import { TestEvents } from './utils.js'; describe('EventBridge ', () => { diff --git a/packages/parser/tests/unit/schema/kafka.test.ts b/packages/parser/tests/unit/schema/kafka.test.ts index 1296130dd8..952a4eb21b 100644 --- a/packages/parser/tests/unit/schema/kafka.test.ts +++ b/packages/parser/tests/unit/schema/kafka.test.ts @@ -7,7 +7,7 @@ import { KafkaMskEventSchema, KafkaSelfManagedEventSchema, -} from '../../../src/schemas/kafka.js'; +} from '../../../src/schemas'; import { TestEvents } from './utils.js'; describe('Kafka ', () => { diff --git a/packages/parser/tests/unit/schema/kinesis.test.ts b/packages/parser/tests/unit/schema/kinesis.test.ts index 8a9aabadec..1cc88aafb3 100644 --- a/packages/parser/tests/unit/schema/kinesis.test.ts +++ b/packages/parser/tests/unit/schema/kinesis.test.ts @@ -4,11 +4,11 @@ * @group unit/parser/schema/ */ -import { KinesisDataStreamSchema } from '../../../src/schemas/kinesis.js'; +import { KinesisDataStreamSchema } from '../../../src/schemas'; import { KinesisFirehoseSchema, KinesisFirehoseSqsSchema, -} from '../../../src/schemas/kinesis-firehose.js'; +} from '../../../src/schemas'; import { TestEvents } from './utils.js'; describe('Kinesis ', () => { diff --git a/packages/parser/tests/unit/schema/lambda.test.ts b/packages/parser/tests/unit/schema/lambda.test.ts index cd789704bc..cf43eb4fd2 100644 --- a/packages/parser/tests/unit/schema/lambda.test.ts +++ b/packages/parser/tests/unit/schema/lambda.test.ts @@ -4,7 +4,7 @@ * @group unit/parser/schema/ */ -import { LambdaFunctionUrlSchema } from '../../../src/schemas/lambda.js'; +import { LambdaFunctionUrlSchema } from '../../../src/schemas'; import { TestEvents } from './utils.js'; describe('Lambda ', () => { diff --git a/packages/parser/tests/unit/schema/s3.test.ts b/packages/parser/tests/unit/schema/s3.test.ts index eff1bb6840..7d23da0d8c 100644 --- a/packages/parser/tests/unit/schema/s3.test.ts +++ b/packages/parser/tests/unit/schema/s3.test.ts @@ -9,7 +9,7 @@ import { S3SqsEventNotificationSchema, S3Schema, S3ObjectLambdaEventSchema, -} from '../../../src/schemas/s3.js'; +} from '../../../src/schemas'; import { TestEvents } from './utils.js'; describe('S3 ', () => { diff --git a/packages/parser/tests/unit/schema/ses.test.ts b/packages/parser/tests/unit/schema/ses.test.ts index 3d714ea074..bc7f17f53c 100644 --- a/packages/parser/tests/unit/schema/ses.test.ts +++ b/packages/parser/tests/unit/schema/ses.test.ts @@ -4,7 +4,7 @@ * @group unit/parser/schema/ */ -import { SesSchema } from '../../../src/schemas/ses.js'; +import { SesSchema } from '../../../src/schemas'; import { TestEvents } from './utils.js'; describe('Schema:', () => { diff --git a/packages/parser/tests/unit/schema/sns.test.ts b/packages/parser/tests/unit/schema/sns.test.ts index 1875d20642..c07b98fe07 100644 --- a/packages/parser/tests/unit/schema/sns.test.ts +++ b/packages/parser/tests/unit/schema/sns.test.ts @@ -4,7 +4,7 @@ * @group unit/parser/schema/ */ -import { SnsSchema } from '../../../src/schemas/sns.js'; +import { SnsSchema } from '../../../src/schemas'; import { TestEvents } from './utils.js'; describe('Schema:', () => { diff --git a/packages/parser/tests/unit/schema/sqs.test.ts b/packages/parser/tests/unit/schema/sqs.test.ts index 802c36da08..d228b44cd2 100644 --- a/packages/parser/tests/unit/schema/sqs.test.ts +++ b/packages/parser/tests/unit/schema/sqs.test.ts @@ -4,7 +4,7 @@ * @group unit/parser/schema/ */ -import { SqsSchema } from '../../../src/schemas/sqs.js'; +import { SqsSchema } from '../../../src/schemas'; import { TestEvents } from './utils.js'; describe('SQS ', () => { diff --git a/packages/parser/tests/unit/schema/vpc-lattice.test.ts b/packages/parser/tests/unit/schema/vpc-lattice.test.ts index 576efa623f..62a67acbed 100644 --- a/packages/parser/tests/unit/schema/vpc-lattice.test.ts +++ b/packages/parser/tests/unit/schema/vpc-lattice.test.ts @@ -4,7 +4,7 @@ * @group unit/parser/schema/ */ -import { VpcLatticeSchema } from '../../../src/schemas/vpc-lattice.js'; +import { VpcLatticeSchema } from '../../../src/schemas'; import { TestEvents } from './utils.js'; describe('VPC Lattice ', () => { diff --git a/packages/parser/tests/unit/schema/vpc-latticev2.test.ts b/packages/parser/tests/unit/schema/vpc-latticev2.test.ts index e93deb24c1..0b275e82e3 100644 --- a/packages/parser/tests/unit/schema/vpc-latticev2.test.ts +++ b/packages/parser/tests/unit/schema/vpc-latticev2.test.ts @@ -4,7 +4,7 @@ * @group unit/parser/schema/ */ -import { VpcLatticeV2Schema } from '../../../src/schemas/vpc-latticev2.js'; +import { VpcLatticeV2Schema } from '../../../src/schemas'; import { TestEvents } from './utils.js'; describe('VpcLatticeV2 ', () => { From 967e70c3411ddcd6e9a742f90e659a89c0133f19 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Thu, 4 Jan 2024 06:16:10 +0100 Subject: [PATCH 03/23] remove unnecessary exports --- packages/parser/src/schemas/cloudformation-custom-resource.ts | 1 - packages/parser/src/schemas/index.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/parser/src/schemas/cloudformation-custom-resource.ts b/packages/parser/src/schemas/cloudformation-custom-resource.ts index 13f9e9760d..84369dbdae 100644 --- a/packages/parser/src/schemas/cloudformation-custom-resource.ts +++ b/packages/parser/src/schemas/cloudformation-custom-resource.ts @@ -36,5 +36,4 @@ export { CloudFormationCustomResourceCreateSchema, CloudFormationCustomResourceDeleteSchema, CloudFormationCustomResourceUpdateSchema, - CloudFormationCustomResourceBaseSchema, }; diff --git a/packages/parser/src/schemas/index.ts b/packages/parser/src/schemas/index.ts index 0a215038f3..335846ad88 100644 --- a/packages/parser/src/schemas/index.ts +++ b/packages/parser/src/schemas/index.ts @@ -2,7 +2,6 @@ export { AlbSchema, AlbMultiValueHeadersSchema } from './alb.js'; export { APIGatewayProxyEventSchema } from './apigw.js'; export { APIGatewayProxyEventV2Schema } from './apigwv2.js'; export { - CloudFormationCustomResourceBaseSchema, CloudFormationCustomResourceCreateSchema, CloudFormationCustomResourceDeleteSchema, CloudFormationCustomResourceUpdateSchema, From 25762735933325bb9ee2eb4ad5a20a34817dde94 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Thu, 4 Jan 2024 11:11:21 +0100 Subject: [PATCH 04/23] add custom validation --- docs/snippets/parser/manual.ts | 2 +- docs/snippets/parser/refine.ts | 21 +++++++++++++++++++++ docs/utilities/parser.md | 21 +++++++++++++++------ 3 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 docs/snippets/parser/refine.ts diff --git a/docs/snippets/parser/manual.ts b/docs/snippets/parser/manual.ts index a5997dc1f2..b9dd3c9605 100644 --- a/docs/snippets/parser/manual.ts +++ b/docs/snippets/parser/manual.ts @@ -25,6 +25,6 @@ export const handler = async ( const parsed = EventBridgeSchema.parse(event); // (1) console.log(parsed); - const orders: Order[] = eventBridgeEnvelope(event, orderSchema); // (2) + const orders: Order = eventBridgeEnvelope(event, orderSchema); // (2) console.log(orders); }; diff --git a/docs/snippets/parser/refine.ts b/docs/snippets/parser/refine.ts new file mode 100644 index 0000000000..4a701240e8 --- /dev/null +++ b/docs/snippets/parser/refine.ts @@ -0,0 +1,21 @@ +import { z } from 'zod'; + +const orderItemSchema = z.object({ + id: z.number().positive(), + quantity: z.number(), + description: z.string(), +}); + +export const orderSchema = z + .object({ + id: z.number().positive(), + description: z.string(), + items: z.array(orderItemSchema).refine((items) => items.length > 0, { + message: 'Order must have at least one item', + }), + optionalField: z.string().optional(), + }) + .refine((order) => order.id > 100 && order.items.length > 100, { + message: + 'All orders with more than 100 items must have an id greater than 100', + }); diff --git a/docs/utilities/parser.md b/docs/utilities/parser.md index f63cd8a585..f2ae45c34a 100644 --- a/docs/utilities/parser.md +++ b/docs/utilities/parser.md @@ -161,17 +161,26 @@ Parser comes with the following built-in envelopes: You can use built-in envelopes and schemas to parse the incoming events manually: -```typescript ---8<-- "docs/snippets/parser/manual.ts" -``` -1. Use `SqsSchema` to parse the event, the `Records` will be parsed as string. You have to parse the records manually +=== "Manual parsing" + ```typescript hl_lines="25 28" + --8<-- "docs/snippets/parser/manual.ts" + ``` + + 1. Use `EventBridgeSchema` to parse the event, the `details` fields will be parsed as a generic record. + 2. Use `eventBridgeEnvelope` with a combination of `orderSchema` to get `Order` object from the `details` field. -## Types +## Custom validation +Because Parser uses zod, you can use all the features of zod to validate your data. +For example, you can use `refine` to validate a field or a combination of fields: +=== "Custom validation" + ```typescript hl_lines="13 18" + --8<-- "docs/snippets/parser/refine.ts" + ``` -## FAQs +Zod provides a lot of other features and customization, see [zod documentation](https://zod.dev) for more details. From e97c729c4f111f826e4fd3a4d8edd1249591feec Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Thu, 4 Jan 2024 11:22:01 +0100 Subject: [PATCH 05/23] remove unnecessary export --- docs/snippets/parser/decorator.ts | 2 +- docs/snippets/parser/envelopeDecorator.ts | 3 +-- docs/snippets/parser/extend.ts | 5 ++--- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/docs/snippets/parser/decorator.ts b/docs/snippets/parser/decorator.ts index 585206b1bc..a8151d5f7a 100644 --- a/docs/snippets/parser/decorator.ts +++ b/docs/snippets/parser/decorator.ts @@ -28,5 +28,5 @@ class Lambda extends LambdaInterface { } } -export const myFunction = new Lambda(); +const myFunction = new Lambda(); export const handler = myFunction.handler.bind(myFunction); diff --git a/docs/snippets/parser/envelopeDecorator.ts b/docs/snippets/parser/envelopeDecorator.ts index 3563c09f49..5174fe3986 100644 --- a/docs/snippets/parser/envelopeDecorator.ts +++ b/docs/snippets/parser/envelopeDecorator.ts @@ -22,7 +22,6 @@ type Order = z.infer; class Lambda extends LambdaInterface { @parser({ schema: orderSchema, envelope: eventBridgeEnvelope }) // (1) public async handler(event: Order, _context: Context): Promise { - // eslint-disable-next-line @typescript-eslint/no-unused-vars for (const item of event.items) { // item is parsed as OrderItem (2) console.log(item.id); @@ -30,5 +29,5 @@ class Lambda extends LambdaInterface { } } -export const myFunction = new Lambda(); +const myFunction = new Lambda(); export const handler = myFunction.handler.bind(myFunction); diff --git a/docs/snippets/parser/extend.ts b/docs/snippets/parser/extend.ts index 80288a4350..79803661c6 100644 --- a/docs/snippets/parser/extend.ts +++ b/docs/snippets/parser/extend.ts @@ -18,8 +18,7 @@ const orderSchema = z.object({ }); const orderEventSchema = EventBridgeSchema.extend({ - // (1) - detail: orderSchema, + detail: orderSchema, // (1) }); type OrderEvent = z.infer; @@ -34,5 +33,5 @@ class Lambda extends LambdaInterface { } } -export const myFunction = new Lambda(); +const myFunction = new Lambda(); export const handler = myFunction.handler.bind(myFunction); From 6ee1d43a06b6da04dca42d5715a6be6ac019e699 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Thu, 4 Jan 2024 11:30:28 +0100 Subject: [PATCH 06/23] add warning --- docs/utilities/parser.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/utilities/parser.md b/docs/utilities/parser.md index f2ae45c34a..502f984dba 100644 --- a/docs/utilities/parser.md +++ b/docs/utilities/parser.md @@ -3,6 +3,10 @@ title: Parser (zod) descrition: Utility --- + +???+ warning +**This utility is currently released as beta developer preview** and is intended strictly for feedback and testing purposes **and not for production workloads**. The version and all future versions tagged with the `-beta` suffix should be treated as not stable. Up until before the [General Availability release](https://github.com/aws-powertools/powertools-lambda-typescript/milestone/16) we might introduce significant breaking changes and improvements in response to customers feedback. + This utility provides data validation and parsing using [zod](https://zod.dev). ## Key features From 81e7ad196082f1fe5c4ae77e1aaa47754d51890f Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Thu, 4 Jan 2024 11:34:25 +0100 Subject: [PATCH 07/23] remove duplicate imports --- packages/parser/tests/unit/schema/kinesis.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/parser/tests/unit/schema/kinesis.test.ts b/packages/parser/tests/unit/schema/kinesis.test.ts index 1cc88aafb3..a51b960450 100644 --- a/packages/parser/tests/unit/schema/kinesis.test.ts +++ b/packages/parser/tests/unit/schema/kinesis.test.ts @@ -4,8 +4,8 @@ * @group unit/parser/schema/ */ -import { KinesisDataStreamSchema } from '../../../src/schemas'; import { + KinesisDataStreamSchema, KinesisFirehoseSchema, KinesisFirehoseSqsSchema, } from '../../../src/schemas'; From b74e20a631989abd32514d780996d2c24dd4770f Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Fri, 5 Jan 2024 14:24:43 +0100 Subject: [PATCH 08/23] add types and error handlig --- docs/snippets/parser/types.ts | 33 +++++++++++++++++++++++++++++++++ docs/utilities/parser.md | 29 +++++++++++++++++++++++++---- 2 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 docs/snippets/parser/types.ts diff --git a/docs/snippets/parser/types.ts b/docs/snippets/parser/types.ts new file mode 100644 index 0000000000..7971090449 --- /dev/null +++ b/docs/snippets/parser/types.ts @@ -0,0 +1,33 @@ +import { Context } from 'aws-lambda'; +import { parser } from '@aws-lambda-powertools/parser/middleware'; +import { z } from 'zod'; +import middy from '@middy/core'; + +const orderItemSchema = z.object({ + id: z.number().positive(), + quantity: z.number(), + description: z.string(), +}); + +const orderSchema = z.object({ + id: z.number().positive(), + description: z.string(), + items: z.array(orderItemSchema), + optionalField: z.string().optional(), +}); + +type Order = z.infer; // (1) + +const lambdaHandler = async ( + event: Order, // (2) + _context: Context +): Promise => { + for (const item of event.items) { + // item is parsed as OrderItem + console.log(item.id); // (3) + } +}; + +export const handler = middy(lambdaHandler).use( + parser({ schema: orderSchema }) +); diff --git a/docs/utilities/parser.md b/docs/utilities/parser.md index 502f984dba..91a86c52dc 100644 --- a/docs/utilities/parser.md +++ b/docs/utilities/parser.md @@ -5,9 +5,10 @@ descrition: Utility ???+ warning -**This utility is currently released as beta developer preview** and is intended strictly for feedback and testing purposes **and not for production workloads**. The version and all future versions tagged with the `-beta` suffix should be treated as not stable. Up until before the [General Availability release](https://github.com/aws-powertools/powertools-lambda-typescript/milestone/16) we might introduce significant breaking changes and improvements in response to customers feedback. + **This utility is currently released as beta developer preview** and is intended strictly for feedback and testing purposes **and not for production workloads**. The version and all future versions tagged with the `-beta` suffix should be treated as not stable. Up until before the [General Availability release](https://github.com/aws-powertools/powertools-lambda-typescript/milestone/16) we might introduce significant breaking changes and improvements in response to customers feedback. -This utility provides data validation and parsing using [zod](https://zod.dev). +This utility provides data validation and parsing using [zod](https://zod.dev){target="_blank"}. +Zod is a TypeScript-first schema declaration and validation library. ## Key features @@ -108,8 +109,6 @@ You can extend them to include your own schema, and yet have all other known fie --8<-- "docs/snippets/parser/examplePayload.json" ``` - - ## Envelopes When trying to parse your payloads wrapped in a known structure, you might encounter the following situations: @@ -187,7 +186,29 @@ For example, you can use `refine` to validate a field or a combination of fields Zod provides a lot of other features and customization, see [zod documentation](https://zod.dev) for more details. +## Types + +## Schema and Type inference +Zod provides a way to extract the TypeScript type of a schema. +This is useful when you want to use the parsed data in your handler: + +=== "Types" + ```typescript hl_lines="19 22 27" + --8<-- "docs/snippets/parser/types.ts" + ``` + + 1. Use `z.infer` to extract the TypeScript type of the schema + 2. Use the type in your handler + 3. TypeScript inferce deeply nested types, here `Order` and `OrderItem` are inferred +## Compatibility with @types/aws-lambda +The package `@types/aws-lambda` contains type definitions for aws-lambda. +Powertools parser utility also bring lambda event types based on the built-in schema definitions. +Both libraries try to provide types for the same events, but they are not compatible with each other yet. +We are working on a sustainable solution to make them compatible and avoid any breaking changes in the future. +We recommend to use the types provided by the parser utility. +## Error handling +We don't have any error handling in the utility and propagate any errors from zod, which are thrown as `ZodError`. From 6f25cafd1044d0e8ebdb3f0890e40829c8863701 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Fri, 5 Jan 2024 14:47:37 +0100 Subject: [PATCH 09/23] remove comment from annotations --- docs/snippets/parser/envelopeDecorator.ts | 6 +++--- docs/snippets/parser/extend.ts | 8 ++++---- docs/snippets/parser/manual.ts | 4 ++-- docs/snippets/parser/types.ts | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/snippets/parser/envelopeDecorator.ts b/docs/snippets/parser/envelopeDecorator.ts index 5174fe3986..68845f68c5 100644 --- a/docs/snippets/parser/envelopeDecorator.ts +++ b/docs/snippets/parser/envelopeDecorator.ts @@ -20,11 +20,11 @@ const orderSchema = z.object({ type Order = z.infer; class Lambda extends LambdaInterface { - @parser({ schema: orderSchema, envelope: eventBridgeEnvelope }) // (1) + @parser({ schema: orderSchema, envelope: eventBridgeEnvelope }) // (1)! public async handler(event: Order, _context: Context): Promise { for (const item of event.items) { - // item is parsed as OrderItem (2) - console.log(item.id); + // item is parsed as OrderItem + console.log(item.id); // (2)! } } } diff --git a/docs/snippets/parser/extend.ts b/docs/snippets/parser/extend.ts index 79803661c6..e4d6da37d0 100644 --- a/docs/snippets/parser/extend.ts +++ b/docs/snippets/parser/extend.ts @@ -18,17 +18,17 @@ const orderSchema = z.object({ }); const orderEventSchema = EventBridgeSchema.extend({ - detail: orderSchema, // (1) + detail: orderSchema, // (1)! }); type OrderEvent = z.infer; class Lambda extends LambdaInterface { - @parser({ schema: orderEventSchema }) // (2) + @parser({ schema: orderEventSchema }) // (2)! public async handler(event: OrderEvent, _context: Context): Promise { for (const item of event.detail.items) { - // process OrderItem // (3) - console.log(item); + // process OrderItem + console.log(item); // (3)! } } } diff --git a/docs/snippets/parser/manual.ts b/docs/snippets/parser/manual.ts index b9dd3c9605..dbfb2c4e63 100644 --- a/docs/snippets/parser/manual.ts +++ b/docs/snippets/parser/manual.ts @@ -22,9 +22,9 @@ export const handler = async ( event: EventBridgeEvent, _context: Context ): Promise => { - const parsed = EventBridgeSchema.parse(event); // (1) + const parsed = EventBridgeSchema.parse(event); // (1)! console.log(parsed); - const orders: Order = eventBridgeEnvelope(event, orderSchema); // (2) + const orders: Order = eventBridgeEnvelope(event, orderSchema); // (2)! console.log(orders); }; diff --git a/docs/snippets/parser/types.ts b/docs/snippets/parser/types.ts index 7971090449..4f6ad1c675 100644 --- a/docs/snippets/parser/types.ts +++ b/docs/snippets/parser/types.ts @@ -16,15 +16,15 @@ const orderSchema = z.object({ optionalField: z.string().optional(), }); -type Order = z.infer; // (1) +type Order = z.infer; // (1)! const lambdaHandler = async ( - event: Order, // (2) + event: Order, // (2)! _context: Context ): Promise => { for (const item of event.items) { // item is parsed as OrderItem - console.log(item.id); // (3) + console.log(item.id); // (3)! } }; From 3d8c9d01ec3c210d3b397a210d64d619977879cd Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Fri, 5 Jan 2024 16:07:48 +0100 Subject: [PATCH 10/23] minor changes --- docs/snippets/parser/manual.ts | 4 ++-- docs/utilities/parser.md | 38 ++++++++++++++++++---------------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/docs/snippets/parser/manual.ts b/docs/snippets/parser/manual.ts index dbfb2c4e63..9aba126018 100644 --- a/docs/snippets/parser/manual.ts +++ b/docs/snippets/parser/manual.ts @@ -22,8 +22,8 @@ export const handler = async ( event: EventBridgeEvent, _context: Context ): Promise => { - const parsed = EventBridgeSchema.parse(event); // (1)! - console.log(parsed); + const parsedEvent = EventBridgeSchema.parse(event); // (1)! + console.log(parsedEvent); const orders: Order = eventBridgeEnvelope(event, orderSchema); // (2)! console.log(orders); diff --git a/docs/utilities/parser.md b/docs/utilities/parser.md index 91a86c52dc..6ae6cd75c5 100644 --- a/docs/utilities/parser.md +++ b/docs/utilities/parser.md @@ -31,11 +31,11 @@ This utility supports zod v3.0.0 and above. You can define your schema using zod: -```typescript +```typescript title="schema.ts" --8<-- "docs/snippets/parser/schema.ts" ``` -This is a schema for order and oder items using zod. +This is a schema for order and order items using zod. You can create more complex schemas using zod, such as nested objects, arrays, unions, etc. see [zod documentation](https://zod.dev) for more details. ## Parse events @@ -66,7 +66,6 @@ Parser comes with the following built-in schemas: | **AlbSchema** | Lambda Event Source payload for Amazon Application Load Balancer | | **APIGatewayProxyEventSchema** | Lambda Event Source payload for Amazon API Gateway | | **APIGatewayProxyEventV2Schema** | Lambda Event Source payload for Amazon API Gateway v2 payload | -| **BedrockAgentEventSchema** | Lambda Event Source payload for Bedrock Agents | | **CloudFormationCustomResourceCreateSchema** | Lambda Event Source payload for AWS CloudFormation `CREATE` operation | | **CloudFormationCustomResourceUpdateSchema** | Lambda Event Source payload for AWS CloudFormation `UPDATE` operation | | **CloudFormationCustomResourceDeleteSchema** | Lambda Event Source payload for AWS CloudFormation `DELETE` operation | @@ -91,7 +90,7 @@ Parser comes with the following built-in schemas: ### Extend built-in schemas -You can extend them to include your own schema, and yet have all other known fields parsed along the way. +You can extend every built-in schema to include your own schema, and yet have all other known fields parsed along the way. === "handler.ts" ```typescript hl_lines="20-22 27 30" @@ -111,15 +110,15 @@ You can extend them to include your own schema, and yet have all other known fie ## Envelopes -When trying to parse your payloads wrapped in a known structure, you might encounter the following situations: +When trying to parse your payload you might encounter the following situations: * Your actual payload is wrapped around a known structure, for example Lambda Event Sources like EventBridge * You're only interested in a portion of the payload, for example parsing the detail of custom events in EventBridge, or body of SQS records * You can either solve these situations by creating a schema of these known structures, parsing them, then extracting and parsing a key where your payload is. This can become difficult quite quickly. Parser simplifies the development through a feature named Envelope. -Envelopes can be used via envelope parameter available in both parse function and `parser` decorator. -Here's an example of parsing a schema found in an event coming from EventBridge, where all you want is what's inside the detail key. +Envelopes can be used via envelope parameter available in middy and decorator. +Here's an example of parsing a custom schema in an event coming from EventBridge, where all you want is what's inside the detail key. === "Decorator" ```typescript hl_lines="5 23" @@ -138,6 +137,10 @@ The envelopes are functions that take an event and the schema to parse, and retu Depending on the envelope it can be something simple like extracting a key. We have also complex envelopes that parse the payload from a string, decode base64, uncompress gzip, etc. +!!! tip "Envelopes vs schema extension" + Use envelopes if you want to extract only the inner part of an event payload and don't use the information from the Lambda event. + Otherwise, extend built-in schema to parse the whole payload and use the metadata from the Lambda event. + ### Built-in envelopes Parser comes with the following built-in envelopes: @@ -188,27 +191,26 @@ Zod provides a lot of other features and customization, see [zod documentation]( ## Types -## Schema and Type inference -Zod provides a way to extract the TypeScript type of a schema. -This is useful when you want to use the parsed data in your handler: +### Schema and Type inference +Zod provides a way to extract the type of schema, so you can use it in your handler: === "Types" ```typescript hl_lines="19 22 27" --8<-- "docs/snippets/parser/types.ts" ``` - 1. Use `z.infer` to extract the TypeScript type of the schema - 2. Use the type in your handler - 3. TypeScript inferce deeply nested types, here `Order` and `OrderItem` are inferred + 1. Use `z.infer` to extract the type of the schema + 2. `event` is typed as `Order` object + 3. we can infer deeply nested types, here `Order` and `OrderItem` are inferred -## Compatibility with @types/aws-lambda +### Compatibility with @types/aws-lambda -The package `@types/aws-lambda` contains type definitions for aws-lambda. -Powertools parser utility also bring lambda event types based on the built-in schema definitions. -Both libraries try to provide types for the same events, but they are not compatible with each other yet. +The package `@types/aws-lambda` contains type definitions for AWS service event invocations. +Powertools parser utility also bring AWS Lambda event types based on the built-in schema definitions. +Both libraries try to provide types for the same event structure, but they might not be compatible with each other yet. We are working on a sustainable solution to make them compatible and avoid any breaking changes in the future. We recommend to use the types provided by the parser utility. ## Error handling -We don't have any error handling in the utility and propagate any errors from zod, which are thrown as `ZodError`. +We don't have any error handling in the utility and propagate all errors from zod, which are thrown as `ZodError`. From 67cac21357ca9e3ef95be8c323bac439e6133737 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Tue, 2 Apr 2024 14:17:08 +0200 Subject: [PATCH 11/23] revert merge changes --- .devcontainer/Dockerfile | 21 +- .devcontainer/devcontainer.json | 5 +- .github/CODEOWNERS | 2 +- .../actions/cached-node-modules/action.yml | 8 +- .github/actions/create-pr/action.yml | 92 + .../create-pr/create_pr_for_staged_changes.sh | 148 + .github/boring-cyborg.yml | 2 +- .github/dependabot.yml | 50 + .../label_missing_acknowledgement_section.js | 50 + .github/semantic.yml | 2 + .github/workflows/closed-issues-message.yml | 17 - .github/workflows/dependency-review.yml | 22 + .github/workflows/dispatch_analytics.yml | 55 +- .github/workflows/label_pr_on_title.yml | 31 +- .github/workflows/make-release.yml | 73 +- .github/workflows/make-v2-release.yml | 80 - .github/workflows/make-version.yml | 51 + .github/workflows/measure-packages-size.yml | 40 - .github/workflows/on-doc-v2-merge.yml | 22 - .github/workflows/on-merge-to-main.yml | 50 - .github/workflows/on-workflows-push-pr.yml | 19 - .github/workflows/on_closed_issues.yml | 34 + .github/workflows/on_doc_merge.yml | 10 +- .github/workflows/on_merged_pr.yml | 64 + .github/workflows/on_opened_pr.yml | 53 +- .github/workflows/on_pr_updates.yml | 35 + .github/workflows/ossf_scorecard.yml | 48 + .github/workflows/post-release.yml | 7 +- .../pr-run-linting-check-and-unit-tests.yml | 6 +- .github/workflows/publish_layer.yml | 74 +- .github/workflows/rebuild-latest-docs.yml | 26 - .github/workflows/rebuild_latest_docs.yml | 37 + .github/workflows/record_pr.yml | 50 +- .github/workflows/release-drafter.yml | 2 +- ...sable-run-linting-check-and-unit-tests.yml | 41 +- .../workflows/reusable_deploy_layer_stack.yml | 31 +- .../workflows/reusable_export_pr_details.yml | 32 +- ...ish-docs.yml => reusable_publish_docs.yml} | 51 +- .../reusable_update_layer_arn_docs.yml | 52 - .github/workflows/run-e2e-tests.yml | 19 +- .github/workflows/secure-workflows.yml | 37 + .github/workflows/stale-issues.yml | 5 +- .gitignore | 3 +- .gitpod.Dockerfile | 16 + .gitpod.yml | 12 +- .husky/pre-commit | 3 - .husky/pre-push | 3 - .nvmrc | 2 +- CHANGELOG.md | 68 + README.md | 15 +- docs/Dockerfile | 7 +- docs/contributing/setup.md | 4 +- docs/contributing/testing.md | 2 +- docs/core/logger.md | 113 +- docs/core/metrics.md | 23 +- docs/core/tracer.md | 29 +- docs/index.md | 82 +- docs/maintainers.md | 108 +- docs/media/logos/appyourself.svg | 43 + docs/overrides/main.html | 5 + docs/requirements.in | 4 + docs/requirements.txt | 469 +- docs/roadmap.md | 2 +- docs/snippets/CHANGELOG.md | 24 + .../batch/advancedTracingRecordHandler.ts | 3 +- docs/snippets/batch/customPartialProcessor.ts | 2 +- docs/snippets/batch/extendingFailure.ts | 12 +- .../batch/gettingStartedErrorHandling.ts | 2 +- .../batch/templates/sam/dynamodb.yaml | 4 +- .../snippets/batch/templates/sam/kinesis.yaml | 2 +- docs/snippets/batch/templates/sam/sqs.yaml | 4 +- docs/snippets/batch/testingYourCode.ts | 18 +- .../idempotency/idempotentDecoratorBase.ts | 2 +- .../idempotency/templates/tableCdk.ts | 2 +- .../idempotency/templates/tableSam.yaml | 2 +- .../idempotency/templates/tableTerraform.tf | 2 +- .../logger/bringYourOwnFormatterClass.ts | 7 +- .../logger/bringYourOwnFormatterHandler.ts | 8 +- docs/snippets/logger/clearStateDecorator.ts | 11 +- docs/snippets/logger/clearStateMiddy.ts | 7 +- docs/snippets/logger/decorator.ts | 2 +- docs/snippets/logger/eventDecorator.ts | 2 +- docs/snippets/logger/eventMiddy.ts | 3 +- docs/snippets/logger/manual.ts | 6 +- docs/snippets/logger/middy.ts | 3 +- docs/snippets/logger/unitTesting.ts | 20 +- .../metrics/addHighResolutionMetric.ts | 4 +- docs/snippets/metrics/addMetadata.ts | 9 +- docs/snippets/metrics/basicUsage.ts | 4 +- .../captureColdStartMetricDecorator.ts | 6 +- .../metrics/captureColdStartMetricMiddy.ts | 9 +- docs/snippets/metrics/createMetrics.ts | 4 +- docs/snippets/metrics/customDimensions.ts | 4 +- docs/snippets/metrics/decorator.ts | 6 +- docs/snippets/metrics/defaultDimensions.ts | 4 +- .../metrics/defaultDimensionsDecorator.ts | 6 +- .../metrics/defaultDimensionsMiddy.ts | 9 +- docs/snippets/metrics/manual.ts | 4 +- docs/snippets/metrics/middy.ts | 9 +- docs/snippets/metrics/multiValueMetrics.ts | 6 +- docs/snippets/metrics/sam.ts | 4 +- docs/snippets/metrics/setDefaultDimensions.ts | 4 +- .../singleMetricDifferentDimsDecorator.ts | 8 +- .../metrics/singleMetricDifferentDimsMiddy.ts | 11 +- docs/snippets/metrics/throwOnEmptyMetrics.ts | 9 +- docs/snippets/package.json | 21 +- .../appConfigProviderCustomClient.ts | 2 + .../parameters/customProviderVault.ts | 9 +- .../parameters/customProviderVaultTypes.ts | 15 +- .../dynamoDBProviderCustomClient.ts | 5 +- .../testingYourCodeProvidersJestMock.ts | 5 +- docs/snippets/tracer/accessRootTraceId.ts | 2 +- .../snippets/tracer/captureMethodDecorator.ts | 2 +- docs/snippets/tracer/decorator.ts | 2 +- .../tracer/disableCaptureResponseHandler.ts | 2 +- .../tracer/disableCaptureResponseMethod.ts | 2 +- .../tracer/disableCaptureResponseMiddy.ts | 3 +- docs/snippets/tracer/middy.ts | 3 +- docs/upgrade.md | 299 +- docs/utilities/batch.md | 7 + docs/utilities/idempotency.md | 21 +- docs/utilities/parameters.md | 2 +- docs/versioning.md | 63 + examples/cdk/CHANGELOG.md | 56 + examples/cdk/package.json | 39 +- examples/cdk/src/example-stack.ts | 8 +- examples/sam/CHANGELOG.md | 59 + examples/sam/package.json | 32 +- examples/sam/template.yaml | 10 +- layers/CHANGELOG.md | 59 + layers/bin/layers.ts | 2 +- layers/package.json | 10 +- layers/src/canary-stack.ts | 4 +- layers/src/layer-publisher-stack.ts | 10 +- layers/tests/e2e/constants.ts | 2 +- layers/tests/e2e/layerPublisher.test.ts | 10 +- layers/tests/unit/layer-publisher.test.ts | 2 +- lerna.json | 2 +- mkdocs.yml | 43 +- package-lock.json | 6462 +++++++++-------- package.json | 47 +- packages/batch/CHANGELOG.md | 59 + packages/batch/README.md | 2 + packages/batch/package.json | 3 +- .../helpers/populateEnvironmentVariables.ts | 2 +- packages/commons/CHANGELOG.md | 59 + packages/commons/README.md | 8 +- packages/commons/package.json | 2 +- packages/commons/src/awsSdkUtils.ts | 5 +- .../src/config/EnvironmentVariablesService.ts | 14 +- .../ConfigServiceInterface.ts} | 22 +- packages/commons/src/types/index.ts | 1 + packages/commons/src/version.ts | 2 +- .../unit/EnvironmentVariablesService.test.ts | 50 + packages/idempotency/CHANGELOG.md | 60 + packages/idempotency/README.md | 2 + packages/idempotency/package.json | 13 +- .../idempotency/src/IdempotencyHandler.ts | 21 +- packages/idempotency/src/errors.ts | 20 +- .../idempotency/src/idempotencyDecorator.ts | 4 +- .../src/persistence/BasePersistenceLayer.ts | 58 +- .../persistence/DynamoDBPersistenceLayer.ts | 25 +- .../src/types/ConfigServiceInterface.ts | 25 +- packages/idempotency/tests/e2e/constants.ts | 2 +- .../tests/unit/IdempotencyHandler.test.ts | 22 + .../tests/unit/idempotencyDecorator.test.ts | 59 +- .../persistence/BasePersistenceLayer.test.ts | 107 +- .../DynamoDbPersistenceLayer.test.ts | 43 +- packages/logger/CHANGELOG.md | 62 + packages/logger/README.md | 8 +- packages/logger/package.json | 7 +- packages/logger/src/Logger.ts | 58 +- .../src/config/EnvironmentVariablesService.ts | 44 +- packages/logger/src/formatter/LogFormatter.ts | 23 +- packages/logger/src/middleware/middy.ts | 3 +- .../src/types/ConfigServiceInterface.ts | 43 +- .../tests/e2e/basicFeatures.middy.test.ts | 2 +- packages/logger/tests/e2e/constants.ts | 4 +- .../tests/e2e/sampleRate.decorator.test.ts | 2 +- .../helpers/populateEnvironmentVariables.ts | 2 +- .../unit/EnvironmentVariablesService.test.ts | 89 +- packages/logger/tests/unit/Logger.test.ts | 34 +- .../formatter/PowertoolsLogFormatter.test.ts | 253 +- .../tests/unit/middleware/middy.test.ts | 6 + packages/metrics/CHANGELOG.md | 62 + packages/metrics/README.md | 8 +- packages/metrics/package.json | 8 +- packages/metrics/src/Metrics.ts | 52 +- .../src/config/EnvironmentVariablesService.ts | 5 + packages/metrics/src/middleware/middy.ts | 3 +- .../src/types/ConfigServiceInterface.ts | 18 +- .../e2e/basicFeatures.decorators.test.ts | 10 +- .../tests/e2e/basicFeatures.manual.test.ts | 6 +- packages/metrics/tests/e2e/constants.ts | 2 +- .../metrics/tests/helpers/metricsUtils.ts | 10 +- packages/metrics/tests/unit/Metrics.test.ts | 84 +- .../tests/unit/middleware/middy.test.ts | 223 +- packages/parameters/CHANGELOG.md | 61 + packages/parameters/README.md | 2 + packages/parameters/package.json | 19 +- .../src/appconfig/AppConfigProvider.ts | 48 +- packages/parameters/src/base/index.ts | 2 +- .../src/config/EnvironmentVariablesService.ts | 10 + packages/parameters/src/constants.ts | 2 + .../src/dynamodb/DynamoDBProvider.ts | 10 +- packages/parameters/src/index.ts | 1 + packages/parameters/src/ssm/SSMProvider.ts | 12 +- .../parameters/src/types/AppConfigProvider.ts | 12 +- .../src/types/ConfigServiceInterface.ts | 24 +- .../parameters/src/types/DynamoDBProvider.ts | 26 +- packages/parameters/src/types/SSMProvider.ts | 28 +- .../parameters/src/types/SecretsProvider.ts | 12 +- packages/parameters/tests/e2e/constants.ts | 2 +- .../tests/unit/AppConfigProvider.test.ts | 57 +- .../tests/unit/BaseProvider.test.ts | 7 +- packages/parser/package.json | 36 +- packages/parser/src/envelopes/apigw.ts | 44 +- packages/parser/src/envelopes/apigwv2.ts | 44 +- packages/parser/src/envelopes/cloudwatch.ts | 61 +- packages/parser/src/envelopes/dynamodb.ts | 69 +- packages/parser/src/envelopes/envelope.ts | 91 +- packages/parser/src/envelopes/event-bridge.ts | 46 +- packages/parser/src/envelopes/index.ts | 26 +- packages/parser/src/envelopes/kafka.ts | 90 +- .../parser/src/envelopes/kinesis-firehose.ts | 59 +- packages/parser/src/envelopes/kinesis.ts | 56 +- packages/parser/src/envelopes/lambda.ts | 52 +- packages/parser/src/envelopes/sns.ts | 135 +- packages/parser/src/envelopes/sqs.ts | 52 +- packages/parser/src/envelopes/vpc-lattice.ts | 50 +- .../parser/src/envelopes/vpc-latticev2.ts | 49 +- packages/parser/src/index.ts | 2 +- packages/parser/src/middleware/parser.ts | 12 +- packages/parser/src/parser.ts | 93 +- packages/parser/src/parserDecorator.ts | 94 + packages/parser/src/schemas/index.ts | 8 +- packages/parser/src/types/ParserOptions.ts | 9 - packages/parser/src/types/envelope.ts | 57 +- packages/parser/src/types/index.ts | 36 + packages/parser/src/types/parser.ts | 30 + packages/parser/src/types/schema.ts | 115 +- packages/parser/tests/unit/envelope.test.ts | 83 + .../tests/unit/envelopes/apigwt.test.ts | 83 +- .../tests/unit/envelopes/apigwv2.test.ts | 88 +- .../tests/unit/envelopes/cloudwatch.test.ts | 142 +- .../tests/unit/envelopes/dynamodb.test.ts | 131 +- .../tests/unit/envelopes/eventbridge.test.ts | 127 +- .../parser/tests/unit/envelopes/kafka.test.ts | 95 +- .../unit/envelopes/kinesis-firehose.test.ts | 169 +- .../tests/unit/envelopes/kinesis.test.ts | 68 +- .../tests/unit/envelopes/lambda.test.ts | 94 +- .../parser/tests/unit/envelopes/sns.test.ts | 160 +- .../parser/tests/unit/envelopes/sqs.test.ts | 79 +- .../tests/unit/envelopes/vpc-lattice.test.ts | 99 +- .../unit/envelopes/vpc-latticev2.test.ts | 99 +- .../tests/unit/parser.decorator.test.ts | 127 +- .../parser/tests/unit/parser.middy.test.ts | 103 +- packages/parser/tests/unit/schema/alb.test.ts | 2 +- .../parser/tests/unit/schema/apigwv2.test.ts | 2 +- .../cloudformation-custom-resource.test.ts | 2 +- .../tests/unit/schema/cloudwatch.test.ts | 2 +- .../parser/tests/unit/schema/dynamodb.test.ts | 2 +- .../tests/unit/schema/eventbridge.test.ts | 2 +- .../parser/tests/unit/schema/kafka.test.ts | 2 +- .../parser/tests/unit/schema/kinesis.test.ts | 2 +- .../parser/tests/unit/schema/lambda.test.ts | 2 +- packages/parser/tests/unit/schema/s3.test.ts | 2 +- packages/parser/tests/unit/schema/ses.test.ts | 2 +- packages/parser/tests/unit/schema/sns.test.ts | 2 +- packages/parser/tests/unit/schema/sqs.test.ts | 2 +- .../tests/unit/schema/vpc-lattice.test.ts | 2 +- .../tests/unit/schema/vpc-latticev2.test.ts | 2 +- packages/testing/CHANGELOG.md | 59 + packages/testing/package.json | 12 +- packages/testing/src/TestInvocationLogs.ts | 2 +- packages/testing/src/constants.ts | 5 +- packages/tracer/CHANGELOG.md | 57 + packages/tracer/README.md | 8 +- packages/tracer/package.json | 15 +- packages/tracer/src/Tracer.ts | 13 +- .../src/config/EnvironmentVariablesService.ts | 30 + packages/tracer/src/middleware/middy.ts | 3 +- .../tracer/src/provider/ProviderService.ts | 14 +- .../src/types/ConfigServiceInterface.ts | 47 +- packages/tracer/tests/e2e/constants.ts | 2 +- packages/tracer/tests/unit/Tracer.test.ts | 15 + tsconfig.json | 2 +- 287 files changed, 10586 insertions(+), 5204 deletions(-) create mode 100644 .github/actions/create-pr/action.yml create mode 100755 .github/actions/create-pr/create_pr_for_staged_changes.sh create mode 100644 .github/dependabot.yml create mode 100644 .github/scripts/label_missing_acknowledgement_section.js delete mode 100644 .github/workflows/closed-issues-message.yml create mode 100644 .github/workflows/dependency-review.yml delete mode 100644 .github/workflows/make-v2-release.yml create mode 100644 .github/workflows/make-version.yml delete mode 100644 .github/workflows/measure-packages-size.yml delete mode 100644 .github/workflows/on-doc-v2-merge.yml delete mode 100644 .github/workflows/on-merge-to-main.yml delete mode 100644 .github/workflows/on-workflows-push-pr.yml create mode 100644 .github/workflows/on_closed_issues.yml create mode 100644 .github/workflows/on_merged_pr.yml create mode 100644 .github/workflows/on_pr_updates.yml create mode 100644 .github/workflows/ossf_scorecard.yml delete mode 100644 .github/workflows/rebuild-latest-docs.yml create mode 100644 .github/workflows/rebuild_latest_docs.yml rename .github/workflows/{reusable-publish-docs.yml => reusable_publish_docs.yml} (78%) delete mode 100644 .github/workflows/reusable_update_layer_arn_docs.yml create mode 100644 .github/workflows/secure-workflows.yml create mode 100644 .gitpod.Dockerfile create mode 100644 docs/media/logos/appyourself.svg create mode 100644 docs/requirements.in create mode 100644 docs/snippets/CHANGELOG.md create mode 100644 docs/versioning.md rename packages/commons/src/{config/ConfigService.ts => types/ConfigServiceInterface.ts} (71%) create mode 100644 packages/parser/src/parserDecorator.ts delete mode 100644 packages/parser/src/types/ParserOptions.ts create mode 100644 packages/parser/src/types/parser.ts create mode 100644 packages/parser/tests/unit/envelope.test.ts diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 65dc112dba..b4a0163a4c 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,13 +1,14 @@ # See here for image contents: https://github.com/microsoft/vscode-dev-containers/blob/v0.212.0/containers/javascript-node/.devcontainer/base.Dockerfile -# [Choice] Node.js version (use -bullseye variants on local arm64/Apple Silicon): 18, 16, 14, 18-bullseye, 16-bullseye, 14-bullseye, 18-buster, 16-buster, 14-buster -ARG VARIANT="18-bullseye" -FROM mcr.microsoft.com/vscode/devcontainers/javascript-node:0-${VARIANT} +FROM mcr.microsoft.com/vscode/devcontainers/javascript-node@sha256:4dbf8b626669df834ca18dbe4b0dc49fcd521b1e0c59b1e56ba47abb39364e2c -# This section to install additional OS packages. -RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ - && apt-get -y install --no-install-recommends bash-completion +# Install fnm to manage Node.js versions +RUN curl -fsSL https://fnm.vercel.app/install -o /tmp/install \ + && chmod a+x /tmp/install \ + && /tmp/install \ + && rm /tmp/install -RUN wget https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip \ - && unzip aws-sam-cli-linux-x86_64.zip -d sam-installation \ - && sudo ./sam-installation/install \ - && rm -rf sam-installation aws-sam-cli-linux-* +# Install AWS SAM CLI +RUN curl -LO https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip \ + && unzip -q aws-sam-cli-linux-x86_64.zip -d sam-installation \ + && sudo ./sam-installation/install \ + && rm -rf sam-installation aws-sam-cli-linux-* \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index e1401b638d..f9033f03d3 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -8,7 +8,7 @@ // Append -bullseye or -buster to pin to an OS version. // Use -bullseye variants on local arm64/Apple Silicon. "args": { - "VARIANT": "18-bullseye" + "VARIANT": "20-bullseye" } }, "customizations": { @@ -16,8 +16,7 @@ "extensions": [ "dbaeumer.vscode-eslint", "esbenp.prettier-vscode", - "firsttris.vscode-jest-runner", - "amazonwebservices.aws-toolkit-vscode" + "firsttris.vscode-jest-runner" ], "vscode": { "git.enableCommitSigning": true diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 5404681454..c08ccc7a94 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,3 @@ # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners -* @aws-powertools/lambda-typescript-core \ No newline at end of file +* @aws-powertools/lambda-typescript-core @aws-powertools/core \ No newline at end of file diff --git a/.github/actions/cached-node-modules/action.yml b/.github/actions/cached-node-modules/action.yml index 6d27b04694..38d6e1e35c 100644 --- a/.github/actions/cached-node-modules/action.yml +++ b/.github/actions/cached-node-modules/action.yml @@ -1,9 +1,9 @@ name: 'Cached Node Modules' description: 'A simple action to cache node_modules or install them if they are not cached' inputs: - nodeVersion: # id of input + nodeVersion: # id of input description: 'Node.js version to use in the cache key' - default: '18' + default: '20' build: description: 'Whether to build the packages or not' default: 'true' @@ -15,11 +15,12 @@ runs: using: "composite" steps: - name: Install npm + # We need to keep this npm version until we drop Node.js 16 support because Node.js 16 doesn't support npm 10 run: npm i -g npm@next-9 shell: bash - name: Cache node modules id: cache-node-modules - uses: actions/cache@69d9d449aced6a2ede0bc19182fadc3a0a42d2b0 # v3.2.6 + uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0 with: path: '**/node_modules' # Use the combo between node version, name, and SHA-256 hash of the lock file as cache key so that @@ -44,6 +45,5 @@ runs: npm run build -w packages/parameters & \ npm run build -w packages/idempotency & \ npm run build -w packages/batch & \ - npm run build -w packages/parser & \ npm run build -w packages/testing shell: bash \ No newline at end of file diff --git a/.github/actions/create-pr/action.yml b/.github/actions/create-pr/action.yml new file mode 100644 index 0000000000..470262609e --- /dev/null +++ b/.github/actions/create-pr/action.yml @@ -0,0 +1,92 @@ +name: "Create PR custom action" +description: "Create a PR and a temporary branch, close duplicates" + +# PROCESS +# +# 1. Setup git client using Powertools for AWS Lambda bot username +# 2. Pushes staged files to a temporary branch +# 3. Creates a PR from temporary branch against a target branch (typically trunk: develop, main, etc.) +# 4. Searches for duplicate PRs with the same title +# 5. If duplicates are found, link to the most recent one, close and delete their branches so we keep a single PR +# 6. In the event of failure, we delete the now orphaned branch (if any), and propagate the failure + +# REQUIREMENTS +# You need to enable "Allow GitHub Actions to create and approve pull requests" in your repository settings +# You need to have "skip-changelog" label in your repository to skip changelog generation. + +# USAGE +# +# - name: Create PR +# id: create-pr +# uses: ./.github/actions/create-pr +# with: +# files: "CHANGELOG.md" +# temp_branch_prefix: "ci-changelog" +# pull_request_title: "chore(ci): changelog rebuild" +# github_token: ${{ secrets.GITHUB_TOKEN }} +# - name: Step to demonstrate how to access outputs (no need for this) +# run: | +# echo "PR number: ${PR_ID}" +# echo "Branch: ${BRANCH}" +# env: +# PR_ID: ${{ steps.create-pr.outputs.pull_request_id}} +# BRANCH: ${{ steps.create-pr.outputs.temp_branch}} + +inputs: + files: + description: "Files to add separated by space" + required: true + temp_branch_prefix: + description: "Prefix for temporary git branch to be created, e.g, ci-docs" + required: true + pull_request_title: + description: "Pull Request title to use" + required: true + github_token: + description: "GitHub token for GitHub CLI" + required: true + target_branch: + description: "Branch to target when creating a PR against (main, by default)" + required: false + default: main + +outputs: + pull_request_id: + description: "Pull request ID created" + value: ${{ steps.create-pr.outputs.pull_request_id }} + temp_branch: + description: "Temporary branch created with staged changed" + value: ${{ steps.create-pr.outputs.temp_branch }} + +runs: + using: "composite" + steps: + - id: adjust-path + run: echo "${{ github.action_path }}" >> $GITHUB_PATH + shell: bash + - id: setup-git + name: Git client setup and refresh tip + run: | + git config --global user.name 'aws-powertools-bot' + git config --global user.email '151832416+aws-powertools-bot@users.noreply.github.com' + git config pull.rebase true + git config remote.origin.url >&- + shell: bash + - id: create-pr + working-directory: ${{ env.GITHUB_WORKSPACE }} + run: create_pr_for_staged_changes.sh "${FILES}" + env: + FILES: ${{ inputs.files }} + TEMP_BRANCH_PREFIX: ${{ inputs.temp_branch_prefix }} + PR_TITLE: ${{ inputs.pull_request_title }} + BASE_BRANCH: ${{ inputs.target_branch }} + GH_TOKEN: ${{ inputs.github_token }} + shell: bash + - id: cleanup + name: Cleanup orphaned branch + if: failure() + run: git push origin --delete "${TEMP_BRANCH_PREFIX}-${GITHUB_RUN_ID}" || echo "Must have failed before creating temporary branch; no cleanup needed." + env: + TEMP_BRANCH_PREFIX: ${{ inputs.temp_branch_prefix }} + GITHUB_RUN_ID: ${{ github.run_id }} + shell: bash diff --git a/.github/actions/create-pr/create_pr_for_staged_changes.sh b/.github/actions/create-pr/create_pr_for_staged_changes.sh new file mode 100755 index 0000000000..063a2e0b47 --- /dev/null +++ b/.github/actions/create-pr/create_pr_for_staged_changes.sh @@ -0,0 +1,148 @@ +#!/bin/bash +set -uo pipefail # prevent accessing unset env vars, prevent masking pipeline errors to the next command + +#docs +#title :create_pr_for_staged_changes.sh +#description :This script will create a PR for staged changes, detect and close duplicate PRs. All PRs will be omitted from Release Notes and Changelogs +#author :@heitorlessa +#date :May 8th 2023 +#version :0.1 +#usage :bash create_pr_for_staged_changes.sh {git_staged_files_or_directories_separated_by_space} +#notes :Meant to use in GitHub Actions only. Temporary branch will be named $TEMP_BRANCH_PREFIX-$GITHUB_RUN_ID +#os_version :Ubuntu 22.04.2 LTS +#required_env_vars :PR_TITLE, TEMP_BRANCH_PREFIX, GH_TOKEN +#============================================================================== + +# Sets GitHub Action with error message to ease troubleshooting +function error() { + echo "::error file=${FILENAME}::$1" + exit 1 +} + +function debug() { + TIMESTAMP=$(date -u "+%FT%TZ") # 2023-05-10T07:53:59Z + echo ""${TIMESTAMP}" - $1" +} + +function notice() { + echo "::notice file=${FILENAME}::$1" +} + +function start_span() { + echo "::group::$1" +} + +function end_span() { + echo "::endgroup::" +} + +function has_required_config() { + start_span "Validating required config" + test -z "${TEMP_BRANCH_PREFIX}" && error "TEMP_BRANCH_PREFIX env must be set to create a PR" + test -z "${PR_TITLE}" && error "PR_TITLE env must be set" + test -z "${GH_TOKEN}" && error "GH_TOKEN env must be set for GitHub CLI" + + # Default GitHub Actions Env Vars: https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables + debug "Are we running in GitHub Action environment?" + test -z "${GITHUB_RUN_ID}" && error "GITHUB_RUN_ID env must be set to trace Workflow Run ID back to PR" + test -z "${GITHUB_SERVER_URL}" && error "GITHUB_SERVER_URL env must be set to trace Workflow Run ID back to PR" + test -z "${GITHUB_REPOSITORY}" && error "GITHUB_REPOSITORY env must be set to trace Workflow Run ID back to PR" + + debug "Config validated successfully!" + set_environment_variables + end_span +} + +function set_environment_variables() { + start_span "Setting environment variables" + export readonly WORKFLOW_URL="${GITHUB_SERVER_URL}"/"${GITHUB_REPOSITORY}"/actions/runs/"${GITHUB_RUN_ID}" # e.g., heitorlessa/aws-lambda-powertools-test/actions/runs/4913570678 + export readonly TEMP_BRANCH="${TEMP_BRANCH_PREFIX}"-"${GITHUB_RUN_ID}" # e.g., ci-changelog-4894658712 + export readonly BASE_BRANCH="${BASE_BRANCH:-main}" # e.g., main, defaults to develop if missing + export readonly PR_BODY="This is an automated PR created from the following workflow" + export readonly FILENAME=".github/scripts/$(basename "$0")" + export readonly NO_DUPLICATES_MESSAGE="No duplicated PRs found" + export readonly SKIP_LABEL="skip-changelog" + + end_span +} + +function has_anything_changed() { + start_span "Validating git staged files" + HAS_ANY_SOURCE_CODE_CHANGED="$(git status --porcelain)" + + test -z "${HAS_ANY_SOURCE_CODE_CHANGED}" && debug "Nothing to update; exitting early" && exit 0 + end_span +} + +function create_temporary_branch_with_changes() { + start_span "Creating temporary branch: "${TEMP_BRANCH}"" + git checkout -b "${TEMP_BRANCH}" + + debug "Committing staged files: $*" + echo "$@" | xargs -n1 git add || error "Failed to add staged changes: "$@"" + git commit -m "${PR_TITLE}" + + git push origin "${TEMP_BRANCH}" || error "Failed to create new temporary branch" + end_span +} + +function create_pr() { + start_span "Creating PR against ${TEMP_BRANCH} branch" + # TODO: create label + NEW_PR_URL=$(gh pr create --title "${PR_TITLE}" --body "${PR_BODY}: ${WORKFLOW_URL}" --base "${BASE_BRANCH}" --label "${SKIP_LABEL}" || error "Failed to create PR") # e.g, https://github.com/aws-powertools/powertools-lambda-python/pull/13 + + # greedy remove any string until the last URL path, including the last '/'. https://opensource.com/article/17/6/bash-parameter-expansion + debug "Extracing PR Number from PR URL: "${NEW_PR_URL}"" + NEW_PR_ID="${NEW_PR_URL##*/}" # 13 + export NEW_PR_URL + export NEW_PR_ID + end_span +} + +function close_duplicate_prs() { + start_span "Searching for duplicate PRs" + DUPLICATE_PRS=$(gh pr list --search "${PR_TITLE}" --json number --jq ".[] | select(.number != ${NEW_PR_ID}) | .number") # e.g, 13\n14 + + if [ -z "${DUPLICATE_PRS}" ]; then + debug "No duplicate PRs found" + DUPLICATE_PRS="${NO_DUPLICATES_MESSAGE}" + else + debug "Closing duplicated PRs: "${DUPLICATE_PRS}"" + echo "${DUPLICATE_PRS}" | xargs -L1 gh pr close --delete-branch --comment "Superseded by #${NEW_PR_ID}" + fi + + export readonly DUPLICATE_PRS + end_span +} + +function report_job_output() { + start_span "Updating job outputs" + echo pull_request_id="${NEW_PR_ID}" >>"$GITHUB_OUTPUT" + echo temp_branch="${TEMP_BRANCH}" >>"$GITHUB_OUTPUT" + end_span +} + +function report_summary() { + start_span "Creating job summary" + echo "### Pull request created successfully :rocket: ${NEW_PR_URL}

Closed duplicated PRs: ${DUPLICATE_PRS}" >>"$GITHUB_STEP_SUMMARY" + + notice "PR_URL is: ${NEW_PR_URL}" + notice "PR_BRANCH is: ${TEMP_BRANCH}" + notice "PR_DUPLICATES are: ${DUPLICATE_PRS}" + end_span +} + +function main() { + # Sanity check + has_anything_changed + has_required_config + + create_temporary_branch_with_changes "$@" + create_pr + close_duplicate_prs + + report_job_output + report_summary +} + +main "$@" diff --git a/.github/boring-cyborg.yml b/.github/boring-cyborg.yml index f84f28861a..8b7e65729f 100644 --- a/.github/boring-cyborg.yml +++ b/.github/boring-cyborg.yml @@ -158,7 +158,7 @@ labelPRBasedOnFilePath: ##### Greetings ######################################################################################################## firstPRWelcomeComment: > - Thanks a lot for your first contribution! Please check out our [contributing guidelines](https://github.com/aws-powertools/powertools-lambda-typescript/blob/chore/pr_automation/CONTRIBUTING.md) and don't hesitate to ask whatever you need. + Thanks a lot for your first contribution! Please check out our [contributing guidelines](https://github.com/aws-powertools/powertools-lambda-typescript/blob/main/CONTRIBUTING.md) and don't hesitate to ask whatever you need. In the meantime, check out the #typescript channel on our Powertools for AWS Lambda Discord: [Invite link](https://discord.gg/B8zZKbbyET) diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..b83c97aea3 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,50 @@ +version: 2 +updates: + - package-ecosystem: docker + directory: /.devcontainer + labels: [ ] + schedule: + interval: daily + + - package-ecosystem: github-actions + directory: / + labels: [ ] + schedule: + interval: daily + + - package-ecosystem: docker + directory: /docs + labels: [ ] + schedule: + interval: daily + + - package-ecosystem: pip + directory: /docs + labels: [ ] + schedule: + interval: daily + ignore: + - dependency-name: "mike" + update-types: ["version-update:semver-major"] + + - package-ecosystem: npm + directory: / + labels: [ ] + schedule: + interval: daily + versioning-strategy: increase + ignore: + - dependency-name: "@middy/core" + update-types: [ "version-update:semver-major" ] + groups: + aws-sdk: + patterns: + - "@aws-sdk/**" + - "@smithy/**" + - "aws-sdk-client-mock" + - "aws-sdk-client-mock-jest" + aws-cdk: + patterns: + - "@aws-cdk/**" + - "aws-cdk-lib" + - "aws-cdk" diff --git a/.github/scripts/label_missing_acknowledgement_section.js b/.github/scripts/label_missing_acknowledgement_section.js new file mode 100644 index 0000000000..d066d8bf87 --- /dev/null +++ b/.github/scripts/label_missing_acknowledgement_section.js @@ -0,0 +1,50 @@ +const { + PR_ACTION, + PR_AUTHOR, + PR_BODY, + PR_NUMBER, + IGNORE_AUTHORS, + LABEL_BLOCK, + LABEL_BLOCK_MISSING_LICENSE_AGREEMENT, +} = require('./constants'); + +module.exports = async ({ github, context, core }) => { + if (IGNORE_AUTHORS.includes(PR_AUTHOR)) { + return core.notice('Author in IGNORE_AUTHORS list; skipping...'); + } + + if (PR_ACTION != 'opened') { + return core.notice( + 'Only newly open PRs are labelled to avoid spam; skipping' + ); + } + + const RELATED_ACK_SECTION_REGEX = + /By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice./; + + const isMatch = RELATED_ACK_SECTION_REGEX.exec(PR_BODY); + + if (isMatch == null) { + core.info( + `No acknowledgement section found, maybe the author didn't use the template but there is one.` + ); + + const msg = + "No acknowledgement section found. Please make sure you used the template to open a PR and didn't remove the acknowledgment section. Check the template here: https://github.com/aws-powertools/powertools-lambda-typescript/blob/develop/.github/PULL_REQUEST_TEMPLATE.md#acknowledgment"; + + await Promise.allSettled([ + github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + body: msg, + issue_number: PR_NUMBER, + }), + github.rest.issues.addLabels({ + issue_number: PR_NUMBER, + owner: context.repo.owner, + repo: context.repo.repo, + labels: [LABEL_BLOCK, LABEL_BLOCK_MISSING_LICENSE_AGREEMENT], + }), + ]); + } +}; diff --git a/.github/semantic.yml b/.github/semantic.yml index cd9709530c..26af1db418 100644 --- a/.github/semantic.yml +++ b/.github/semantic.yml @@ -30,6 +30,8 @@ scopes: - tests - internal - maintenance + - deps + - deps-dev # Always validate the PR title # and ignore the commits to lower the entry bar for contribution diff --git a/.github/workflows/closed-issues-message.yml b/.github/workflows/closed-issues-message.yml deleted file mode 100644 index 2ba272de74..0000000000 --- a/.github/workflows/closed-issues-message.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Closed Issue Message -on: - issues: - types: [closed] -jobs: - auto_comment: - runs-on: ubuntu-latest - steps: - - uses: aws-actions/closed-issue-message@36b7048ea77bb834d16e7a7c5b5471ac767a4ca1 # v1.0.0 - with: - # These inputs are both required - repo-token: "${{ secrets.GITHUB_TOKEN }}" - message: | - ### ⚠️ COMMENT VISIBILITY WARNING ⚠️ - Comments on closed issues are hard for our team to see. - If you need more assistance, please either tag a team member or open a new issue that references this one. - If you wish to keep having a conversation with other community members under this issue feel free to do so. \ No newline at end of file diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 0000000000..ef8b379311 --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,22 @@ +# Dependency Review Action +# +# This Action will scan dependency manifest files that change as part of a Pull Request, +# surfacing known-vulnerable versions of the packages declared or updated in the PR. +# Once installed, if the workflow run is marked as required, +# PRs introducing known-vulnerable packages will be blocked from merging. +# +# Source repository: https://github.com/actions/dependency-review-action +name: 'Dependency Review' +on: [pull_request] + +permissions: + contents: read + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: 'Checkout Repository' + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: 'Dependency Review' + uses: actions/dependency-review-action@9129d7d40b8c12c1ed0f60400d00c92d437adcce # v4.1.3 diff --git a/.github/workflows/dispatch_analytics.yml b/.github/workflows/dispatch_analytics.yml index 56bc9fca49..0bfef0d7af 100644 --- a/.github/workflows/dispatch_analytics.yml +++ b/.github/workflows/dispatch_analytics.yml @@ -1,5 +1,15 @@ name: Dispatch analytics +# PROCESS +# +# 1. Trade GitHub JWT token with AWS credentials for the analytics account +# 2. Invoke a Lambda function dispatcher synchronously with the read-only scoped JWT token +# 3. The dispatcher function will call GitHub APIs to read data from the last hour and aggregate for operational analytics + +# USAGE +# +# NOTE: meant to use as a scheduled task only (or manually for debugging purposes). + on: workflow_dispatch: @@ -7,19 +17,7 @@ on: - cron: '0 * * * *' permissions: - id-token: write - actions: read - checks: read contents: read - deployments: read - issues: read - discussions: read - packages: read - pages: read - pull-requests: read - repository-projects: read - security-events: read - statuses: read jobs: dispatch_token: @@ -28,9 +26,23 @@ jobs: group: analytics runs-on: ubuntu-latest environment: analytics + permissions: + id-token: write + actions: read + checks: read + contents: read # previously we needed `write` to use GH_TOKEN in our dispatcher (Lambda) + deployments: read + issues: read + discussions: read + packages: read + pages: read + pull-requests: read + repository-projects: read + security-events: read + statuses: read steps: - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@04b98b3f9e85f563fb061be8751a0352327246b0 # v3.0.1 + uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 with: aws-region: eu-central-1 role-to-assume: ${{ secrets.AWS_ANALYTICS_ROLE_ARN }} @@ -39,7 +51,16 @@ jobs: - name: Invoke Lambda function run: | payload=$(echo -n '{"githubToken": "${{ secrets.GITHUB_TOKEN }}"}' | base64) - aws lambda invoke \ - --function-name ${{ secrets.AWS_ANALYTICS_DISPATCHER_ARN }} \ - --payload "$payload" response.json - cat response.json + response=$(aws lambda invoke \ + --function-name "${{ secrets.AWS_ANALYTICS_DISPATCHER_ARN }}" \ + --payload "$payload" \ + response.json \ + --query 'FunctionError' \ + --output text) + + cat response.json ; echo # add newline at the end + + if [ "$response" != "None" ]; then + echo "Error invoking lambda function: $response. Aborting." + exit 1 + fi \ No newline at end of file diff --git a/.github/workflows/label_pr_on_title.yml b/.github/workflows/label_pr_on_title.yml index f803c0c6a2..e1c6fb581d 100644 --- a/.github/workflows/label_pr_on_title.yml +++ b/.github/workflows/label_pr_on_title.yml @@ -1,13 +1,38 @@ name: Label PR based on title +# PROCESS +# +# 1. Fetch PR details previously saved from untrusted location +# 2. Parse details for safety +# 3. Label PR based on semantic title (e.g., area, change type) + +# USAGE +# +# NOTE: meant to be used with ./.github/workflows/record_pr.yml +# +# Security Note: +# +# This workflow depends on "Record PR" workflow that runs in an untrusted location (forks) instead of `pull_request_target`. +# This enforces zero trust where "Record PR" workflow always runs on fork with zero permissions on GH_TOKEN. +# When "Record PR" completes, this workflow runs in our repository with the appropriate permissions and sanitize inputs. +# +# Coupled with "Approve GitHub Action to run on forks", we have confidence no privilege can be escalated, +# since any malicious change would need to be approved, and upon social engineering, it'll have zero permissions. + on: workflow_run: workflows: ["Record PR details"] types: - completed +permissions: + contents: read + jobs: get_pr_details: + permissions: + actions: read # download PR artifact + contents: read # checkout code # Guardrails to only ever run if PR recording workflow was indeed # run in a PR event and ran successfully if: ${{ github.event.workflow_run.conclusion == 'success' }} @@ -20,11 +45,13 @@ jobs: label_pr: needs: get_pr_details runs-on: ubuntu-latest + permissions: + pull-requests: write # label respective PR steps: - name: Checkout repository - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: "Label PR based on title" - uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 env: PR_NUMBER: ${{ needs.get_pr_details.outputs.prNumber }} PR_TITLE: ${{ needs.get_pr_details.outputs.prTitle }} diff --git a/.github/workflows/make-release.yml b/.github/workflows/make-release.yml index 32ee9c0902..3602d606d2 100644 --- a/.github/workflows/make-release.yml +++ b/.github/workflows/make-release.yml @@ -1,53 +1,93 @@ name: Make Release + +# RELEASE PROCESS +# +# === Automated activities === +# 1. [Quality check] run unit tests, linting, examples, layer, doc snippets +# 2. [Release] publish all packages to npmjs.org using the latest git commit, ensure provenance with NPM_CONFIG_PROVENANCE=true +# 3. [Create tag] create a new git tag using released version, i.e. v1.13.1 +# 4. [Publish layer] build and package layer, kick off the workflow for beta and prod deployment, including canary tests +# 5. [Publish layer] update documentation with the latest layer ARN version of the prod deployment +# 6. [Publish layer] create PR to merge the updated documentation +# +# === Manual activities === +# 1. Kick off `make-version` workflow to bump and review the version changes and changelog for each package +# 2. Merge the PR created by `make-version` workflow +# 3. Kick off this workflow to make the release +# 4. Merge the PR created by the `publish_layer` workflow to update the documentation +# 5. Update draft release notes with the latest changes and publish the release on GitHub + on: workflow_dispatch: {} + +permissions: + contents: read + concurrency: group: on-release-publish + + jobs: run-unit-tests: uses: ./.github/workflows/reusable-run-linting-check-and-unit-tests.yml + # This job publishes the packages to npm. + # It uses the latest git commit sha as the version and ensures provenance with NPM_CONFIG_PROVENANCE flag. + # We don't bump the version because we do that in the `make-version` workflow. + # It also sets the RELEASE_VERSION output to be used by the next job to create a git tag. publish-npm: needs: run-unit-tests # Needed as recommended by npm docs on publishing with provenance https://docs.npmjs.com/generating-provenance-statements permissions: id-token: write - contents: write + environment: Release runs-on: ubuntu-latest outputs: RELEASE_VERSION: ${{ steps.set-release-version.outputs.RELEASE_VERSION }} steps: - name: Checkout code - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: - # Here `token` is needed to avoid incurring in error GH006 Protected Branch Update Failed, - token: ${{ secrets.GH_PUBLISH_TOKEN }} - # While `fetch-depth` is used to allow the workflow to later commit & push the changes. - fetch-depth: 0 + ref: ${{ github.sha }} - name: Setup NodeJS - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: - node-version: "18" + node-version: "20" cache: "npm" - name: Setup auth tokens run: | - git config --global user.name 'github-actions[bot]' - git config --global user.email 'github-actions[bot]@users.noreply.github.com' - git remote set-url origin https://x-access-token:${{ secrets.GH_PUBLISH_TOKEN }}@github.com/$GITHUB_REPOSITORY npm set "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" - name: Setup dependencies uses: ./.github/actions/cached-node-modules - - name: Version - run: | - npx lerna version --conventional-commits --force-publish --no-commit-hooks --yes - name: Publish to npm run: | - NPM_CONFIG_PROVENANCE=true npx lerna publish from-git --yes + NPM_CONFIG_PROVENANCE=true npx lerna publish from-package --git-head ${{ github.sha }} --yes - name: Set release version id: set-release-version run: | VERSION=$(cat lerna.json | jq .version -r) echo RELEASE_VERSION="$VERSION" >> "$GITHUB_OUTPUT" - + + # This job creates a new git tag using the released version (v1.18.1) + create_tag: + needs: [publish-npm] + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + ref: ${{ github.sha }} + - name: Git client setup + run: | + git config --global user.name 'aws-powertools-bot' + git config --global user.email '151832416+aws-powertools-bot@users.noreply.github.com' + git config remote.origin.url >&- + - name: Create git tag + run : | + git tag -a v${{ needs.publish-npm.outputs.RELEASE_VERSION }} -m "Release v${{ needs.publish-npm.outputs.RELEASE_VERSION }}" + git push origin v${{ needs.publish-npm.outputs.RELEASE_VERSION }} + # NOTE: Watch out for the depth limit of 4 nested workflow_calls. # publish_layer -> reusable_deploy_layer_stack -> reusable_update_layer_arn_docs publish_layer: @@ -57,6 +97,7 @@ jobs: id-token: write contents: write pages: write + pull-requests: write uses: ./.github/workflows/publish_layer.yml with: latest_published_version: ${{ needs.publish-npm.outputs.RELEASE_VERSION }} diff --git a/.github/workflows/make-v2-release.yml b/.github/workflows/make-v2-release.yml deleted file mode 100644 index 7571608960..0000000000 --- a/.github/workflows/make-v2-release.yml +++ /dev/null @@ -1,80 +0,0 @@ -name: Make Release v2 (pre-release) -on: - workflow_dispatch: {} -concurrency: - group: on-release-publish -jobs: - run-unit-tests: - uses: ./.github/workflows/reusable-run-linting-check-and-unit-tests.yml - publish-npm: - needs: run-unit-tests - # Needed as recommended by npm docs on publishing with provenance https://docs.npmjs.com/generating-provenance-statements - permissions: - id-token: write - contents: write - runs-on: ubuntu-latest - outputs: - RELEASE_VERSION: ${{ steps.set-release-version.outputs.RELEASE_VERSION }} - steps: - - name: Checkout code - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - - name: Setup NodeJS - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 - with: - node-version: '18' - cache: 'npm' - - name: Setup auth tokens - run: | - npm set "//registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN }}" - - name: Setup dependencies - uses: ./.github/actions/cached-node-modules - with: - # We don't build the packages here as we want to version them first - build: false - - name: Version - run: | - # Version all packages to next major version (2.0.0) without pushing to git, generating changelog or running commit hooks - # Since the version stored in the lerna.json will always be a 1.x.x version, we manually set the version to 2.0.0 - npx lerna version major --force-publish --no-push --no-git-tag-version --no-commit-hooks --no-changelog --yes - - name: Set alpha iteration - run: | - # Get the current alpha version from npm i.e 2.0.0-alpha.0 -> 0, 2.0.0-alpha.1 -> 1 (default to -1 if no alpha versions exist = first pre-release) - ITERATION=$(npm show @aws-lambda-powertools/commons time --json | jq -r 'to_entries | map(select(.key | startswith("2.0.0-alpha"))) | sort_by(.key) | last | .key // "-1"' | cut -d '.' -f 4) - # Write the new version to the file - echo "{ \"iteration\": $((ITERATION + 1)) }" > v2.json - - name: Increment version in UA - run: | - # Increment the version in the UA - echo -e "// this file is auto generated, do not modify\nexport const PT_VERSION = '2.0.0-alpha.$(jq -r '.iteration' v2.json)';" > packages/commons/src/version.ts - - name: Build - run: | - npm run build -w packages/commons & - npm run build -w packages/batch \ - -w packages/idempotency \ - -w packages/logger \ - -w packages/metrics \ - -w packages/parameters \ - -w packages/tracer - - name: Pack packages - run: | - npm pack -w packages/batch \ - -w packages/commons \ - -w packages/idempotency \ - -w packages/logger \ - -w packages/metrics \ - -w packages/parameters \ - -w packages/tracer - - name: Publish to npm - run: | - npm publish aws-lambda-powertools-batch-*.tgz --tag next --provenance - npm publish aws-lambda-powertools-commons-*.tgz --tag next --provenance - npm publish aws-lambda-powertools-idempotency-*.tgz --tag next --provenance - npm publish aws-lambda-powertools-logger-*.tgz --tag next --provenance - npm publish aws-lambda-powertools-metrics-*.tgz --tag next --provenance - npm publish aws-lambda-powertools-parameters-*.tgz --tag next --provenance - npm publish aws-lambda-powertools-tracer-*.tgz --tag next --provenance - - name: Set release version - id: set-release-version - run: | - VERSION="2.0.0-alpha.$(cat v2.json | jq .iteration -r)" - echo RELEASE_VERSION="$VERSION" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/make-version.yml b/.github/workflows/make-version.yml new file mode 100644 index 0000000000..9ff2a457f7 --- /dev/null +++ b/.github/workflows/make-version.yml @@ -0,0 +1,51 @@ +name: Make Version + +on: + workflow_dispatch: { } + +permissions: + contents: read + + +jobs: + bump-version: + permissions: + id-token: write + contents: write + pull-requests: write + runs-on: ubuntu-latest + outputs: + RELEASE_VERSION: ${{ steps.set-release-version.outputs.RELEASE_VERSION }} + steps: + - name: Checkout code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + ref: ${{ github.ref }} + - name: Setup NodeJS + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 + with: + node-version: "20" + cache: "npm" + - name: Setup dependencies + uses: ./.github/actions/cached-node-modules + - name: Version + id: bump-version + run: npx lerna version --conventional-commits --no-git-tag-version --no-push --no-commit-hooks --yes + - name: Update user agent version + run: | + VERSION=$(cat lerna.json | jq .version -r) + echo -e "// this file is auto generated, do not modify\nexport const PT_VERSION = '$VERSION';" > packages/commons/src/version.ts + - name: Stage changes + run: git add . + - name: Set release version + id: set-release-version + run: | + VERSION=$(cat lerna.json | jq .version -r) + echo RELEASE_VERSION="$VERSION" >> "$GITHUB_OUTPUT" + - name: Create PR + id: create-pr + uses: ./.github/actions/create-pr + with: + temp_branch_prefix: "ci-bump" + pull_request_title: "chore(ci): bump version to ${{ steps.set-release-version.outputs.RELEASE_VERSION }}" + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/measure-packages-size.yml b/.github/workflows/measure-packages-size.yml deleted file mode 100644 index ff52dfeaca..0000000000 --- a/.github/workflows/measure-packages-size.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Measure packages size - -on: - workflow_dispatch: - inputs: - prNumber: - description: "PR Number" - required: true - -jobs: - measure-utils-sizes: - runs-on: ubuntu-latest - env: - NODE_ENV: dev - PR_NUMBER: ${{ inputs.prNumber }} - steps: - # Since we are manually triggering the workflow the previous checkout has the main branch. In order to checkout the branch/code of the PR - # we need first to use the PR number to retrieve the PR SHA number. This means we need three steps to: checkout the repo, - # run a custom script to get the SHA, and then finally checkout the PR branch - - name: Checkout Repo - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - - name: Extract PR details - id: extract_PR_details - uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 - with: - script: | - const script = require('.github/scripts/get_pr_info.js'); - await script({github, context, core}); - - name: Checkout PR code - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - with: - ref: ${{ steps.extract_PR_details.outputs.headSHA }} - - name: Packages size report - uses: flochaz/pkg-size-action@1f56793682d897eb0860d98637fa4ea8fe7d37b8 # v.2.0.1 - with: - build-command: mkdir dist && npm run package -w packages/logger -w packages/tracer -w packages/metrics -w packages/commons -w packages/parameters && npm run package-bundle -w packages/logger -w packages/tracer -w packages/metrics -w packages/commons -w packages/parameters && bash -c "mv ./packages/*/dist/* dist/" && ls dist - dist-directory: /dist - pr-number: ${{ inputs.prNumber }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/on-doc-v2-merge.yml b/.github/workflows/on-doc-v2-merge.yml deleted file mode 100644 index 4733c3dba5..0000000000 --- a/.github/workflows/on-doc-v2-merge.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Docs v2 Publish (merge) - -on: - push: - branches: - - feat/v2 - paths: - - "docs/**" - - "mkdocs.yml" - -jobs: - release-docs: - permissions: - contents: write - pages: write - id-token: write - secrets: inherit - uses: ./.github/workflows/reusable-publish-docs.yml - with: - version: next - alias: next - detached_mode: false \ No newline at end of file diff --git a/.github/workflows/on-merge-to-main.yml b/.github/workflows/on-merge-to-main.yml deleted file mode 100644 index 7995d385d1..0000000000 --- a/.github/workflows/on-merge-to-main.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: On PR merge - -on: - workflow_run: - workflows: ["Record PR details"] - types: - - completed -concurrency: - group: on-merge-to-main - -jobs: - get_pr_details: - if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' - uses: ./.github/workflows/reusable_export_pr_details.yml - with: - record_pr_workflow_id: ${{ github.event.workflow_run.id }} - workflow_origin: ${{ github.event.repository.full_name }} - secrets: - token: ${{ secrets.GITHUB_TOKEN }} - run-unit-tests: - needs: get_pr_details - if: ${{ needs.get_pr_details.outputs.prIsMerged == 'true' }} - uses: ./.github/workflows/reusable-run-linting-check-and-unit-tests.yml - update-release-draft: - needs: run-unit-tests - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - - name: Update release draft - uses: release-drafter/release-drafter@569eb7ee3a85817ab916c8f8ff03a5bd96c9c83e # v5.23.0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - release_label_on_merge: - needs: [get_pr_details, update-release-draft] - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - - name: "Label PR related issue for release" - uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 - env: - PR_NUMBER: ${{ needs.get_pr_details.outputs.prNumber }} - PR_BODY: ${{ needs.get_pr_details.outputs.prBody }} - PR_IS_MERGED: ${{ needs.get_pr_details.outputs.prIsMerged }} - PR_AUTHOR: ${{ needs.get_pr_details.outputs.prAuthor }} - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const script = require('.github/scripts/label_related_issue.js') - await script({github, context, core}) diff --git a/.github/workflows/on-workflows-push-pr.yml b/.github/workflows/on-workflows-push-pr.yml deleted file mode 100644 index d8642f5715..0000000000 --- a/.github/workflows/on-workflows-push-pr.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: Lockdown untrusted workflows - -on: - push: - paths: - - ".github/workflows/**" - pull_request: - paths: - - ".github/workflows/**" - -jobs: - enforce_pinned_workflows: - name: Harden Security - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - - name: Ensure 3rd party workflows have SHA pinned - uses: zgosalvez/github-actions-ensure-sha-pinned-actions@21991cec25093947ff3f62e4c223df0260c39944 # v2.1.2 \ No newline at end of file diff --git a/.github/workflows/on_closed_issues.yml b/.github/workflows/on_closed_issues.yml new file mode 100644 index 0000000000..527b0f7d47 --- /dev/null +++ b/.github/workflows/on_closed_issues.yml @@ -0,0 +1,34 @@ +name: Closed Issue Message + +# PROCESS +# +# 1. Comment on recently closed issues to warn future responses may not be looked after + +# USAGE +# +# Always triggered upon issue closure + +on: + issues: + types: [closed] + +permissions: + contents: read + +jobs: + auto_comment: + runs-on: ubuntu-latest + permissions: + issues: write # comment on issues + steps: + - uses: aws-actions/closed-issue-message@36b7048ea77bb834d16e7a7c5b5471ac767a4ca1 # v1.0.0 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" + message: | + ⚠️ **COMMENT VISIBILITY WARNING** ⚠️ + + This issue is now closed. Please be mindful that future comments are hard for our team to see. + + If you need more assistance, please either tag a [team member](https://docs.powertools.aws.dev/lambda/typescript/latest/maintainers/#current-maintainers) or open a new issue that references this one. + + If you wish to keep having a conversation with other community members under this issue feel free to do so. \ No newline at end of file diff --git a/.github/workflows/on_doc_merge.yml b/.github/workflows/on_doc_merge.yml index 2cea171dc8..c977e64624 100644 --- a/.github/workflows/on_doc_merge.yml +++ b/.github/workflows/on_doc_merge.yml @@ -8,14 +8,16 @@ on: - "docs/**" - "mkdocs.yml" +permissions: + contents: read + jobs: release-docs: permissions: - contents: write - pages: write - id-token: write + id-token: write # trade JWT token for AWS credentials in AWS Docs account + contents: read # read from this repo to publish docs secrets: inherit - uses: ./.github/workflows/reusable-publish-docs.yml + uses: ./.github/workflows/reusable_publish_docs.yml with: version: main alias: stage \ No newline at end of file diff --git a/.github/workflows/on_merged_pr.yml b/.github/workflows/on_merged_pr.yml new file mode 100644 index 0000000000..2daae2b1b3 --- /dev/null +++ b/.github/workflows/on_merged_pr.yml @@ -0,0 +1,64 @@ +name: On PR merge + +# PROCESS +# +# 1. Fetch PR details previously saved from untrusted location +# 2. Parse details for safety +# 3. Add `pending-release` label for related issue +# 4. Make a comment in PR if related issue is invalid or can't be labeled + +# USAGE +# +# NOTE: meant to be used with ./.github/workflows/record_pr.yml +# +# Security Note: +# +# This workflow depends on "Record PR" workflow that runs in an untrusted location (forks) instead of `pull_request_target`. +# This enforces zero trust where "Record PR" workflow always runs on fork with zero permissions on GH_TOKEN. +# When "Record PR" completes, this workflow runs in our repository with the appropriate permissions and sanitize inputs. +# +# Coupled with "Approve GitHub Action to run on forks", we have confidence no privilege can be escalated, +# since any malicious change would need to be approved, and upon social engineering, it'll have zero permissions. + +on: + workflow_run: + workflows: ["Record PR details"] + types: + - completed + +permissions: + contents: read + +jobs: + get_pr_details: + if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' + permissions: + actions: read # download PR artifact + contents: read # checkout code + uses: ./.github/workflows/reusable_export_pr_details.yml + with: + record_pr_workflow_id: ${{ github.event.workflow_run.id }} + workflow_origin: ${{ github.event.repository.full_name }} + secrets: + token: ${{ secrets.GITHUB_TOKEN }} + release_label_on_merge: + needs: get_pr_details + runs-on: ubuntu-latest + permissions: + pull-requests: write # make a comment in PR if unable to find related issue + issues: write # label issue with pending-release + if: needs.get_pr_details.outputs.prIsMerged == 'true' + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: "Label PR related issue for release" + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + env: + PR_NUMBER: ${{ needs.get_pr_details.outputs.prNumber }} + PR_BODY: ${{ needs.get_pr_details.outputs.prBody }} + PR_IS_MERGED: ${{ needs.get_pr_details.outputs.prIsMerged }} + PR_AUTHOR: ${{ needs.get_pr_details.outputs.prAuthor }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const script = require('.github/scripts/label_related_issue.js') + await script({github, context, core}) diff --git a/.github/workflows/on_opened_pr.yml b/.github/workflows/on_opened_pr.yml index 0c0b9c62b4..dcd6f0c7ad 100644 --- a/.github/workflows/on_opened_pr.yml +++ b/.github/workflows/on_opened_pr.yml @@ -1,13 +1,39 @@ name: On new PR +# PROCESS +# +# 1. Fetch PR details previously saved from untrusted location +# 2. Parse details for safety +# 3. Confirm there is a related issue for newly opened PR +# 4. Verify if PR template is used and legal acknowledgement hasn't been removed + +# USAGE +# +# NOTE: meant to be used with ./.github/workflows/record_pr.yml +# +# Security Note: +# +# This workflow depends on "Record PR" workflow that runs in an untrusted location (forks) instead of `pull_request_target`. +# This enforces zero trust where "Record PR" workflow always runs on fork with zero permissions on GH_TOKEN. +# When "Record PR" completes, this workflow runs in our repository with the appropriate permissions and sanitize inputs. +# +# Coupled with "Approve GitHub Action to run on forks", we have confidence no privilege can be escalated, +# since any malicious change would need to be approved, and upon social engineering, it'll have zero permissions. + on: workflow_run: workflows: ["Record PR details"] types: - completed +permissions: + contents: read + jobs: get_pr_details: + permissions: + actions: read # download PR artifact + contents: read # checkout code if: ${{ github.event.workflow_run.conclusion == 'success' }} uses: ./.github/workflows/reusable_export_pr_details.yml with: @@ -16,14 +42,14 @@ jobs: secrets: token: ${{ secrets.GITHUB_TOKEN }} check_related_issue: + permissions: + pull-requests: write # label and comment on PR if missing related issue (requirement) needs: get_pr_details runs-on: ubuntu-latest steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - - name: "Debug workflow_run event" - run: echo "${{ github }}" + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: "Ensure related issue is present" - uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 env: PR_BODY: ${{ needs.get_pr_details.outputs.prBody }} PR_NUMBER: ${{ needs.get_pr_details.outputs.prNumber }} @@ -33,4 +59,23 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const script = require('.github/scripts/label_missing_related_issue.js') + await script({github, context, core}) + check_acknowledge_section: + needs: get_pr_details + runs-on: ubuntu-latest + permissions: + pull-requests: write # label and comment on PR if missing acknowledge section (requirement) + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: "Ensure acknowledgement section is present" + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + env: + PR_BODY: ${{ needs.get_pr_details.outputs.prBody }} + PR_NUMBER: ${{ needs.get_pr_details.outputs.prNumber }} + PR_ACTION: ${{ needs.get_pr_details.outputs.prAction }} + PR_AUTHOR: ${{ needs.get_pr_details.outputs.prAuthor }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const script = require('.github/scripts/label_missing_acknowledgement_section.js') await script({github, context, core}) \ No newline at end of file diff --git a/.github/workflows/on_pr_updates.yml b/.github/workflows/on_pr_updates.yml new file mode 100644 index 0000000000..acd301f676 --- /dev/null +++ b/.github/workflows/on_pr_updates.yml @@ -0,0 +1,35 @@ +name: PR requirements + +# PROCESS +# +# 1. Verify whether 'do-not-merge' label is present +# 2. Fail PR to prevent merging until resolved +# 3. Pass PR if do-not-merge label is removed by a maintainer + +# USAGE +# +# Always triggered on PR labeling changes. + +# NOTES +# +# PR requirements are checked async in on_opened_pr.yml and enforced here synchronously +# due to limitations in GH API. + +on: + pull_request: + types: + - opened + - labeled + - unlabeled + +permissions: {} # no permission required + +jobs: + check-requirements: + runs-on: ubuntu-latest + steps: + - name: Block if it doesn't minimum requirements + if: contains(github.event.pull_request.labels.*.name, 'do-not-merge') + run: | + echo "This PR does not meet minimum requirements (check PR comments)." + exit 1 \ No newline at end of file diff --git a/.github/workflows/ossf_scorecard.yml b/.github/workflows/ossf_scorecard.yml new file mode 100644 index 0000000000..506b4fdee3 --- /dev/null +++ b/.github/workflows/ossf_scorecard.yml @@ -0,0 +1,48 @@ +name: Scorecard supply-chain security +on: + # For Branch-Protection check. Only the default branch is supported. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection + branch_protection_rule: + schedule: + - cron: "0 9 * * *" + push: + branches: [main] + workflow_dispatch: + +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + # environment: scorecard + permissions: + security-events: write # update code-scanning dashboard + id-token: write # confirm org+repo identity before publish results + + steps: + - name: "Checkout code" + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 + with: + results_file: results.sarif + results_format: sarif + publish_results: true # publish to OSSF Scorecard REST API + # repo_token: ${{ secrets.SCORECARD_TOKEN }} # read-only fine-grained token to read branch protection settings + + - name: "Upload results" + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard. + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@8a470fddafa5cbb6266ee11b37ef4d8aae19c571 # v3.24.6 + with: + sarif_file: results.sarif diff --git a/.github/workflows/post-release.yml b/.github/workflows/post-release.yml index 8bcceb4573..5bd01b7b6e 100644 --- a/.github/workflows/post-release.yml +++ b/.github/workflows/post-release.yml @@ -12,6 +12,9 @@ on: release: types: [released] +permissions: + contents: read + jobs: post_release: permissions: @@ -23,7 +26,7 @@ jobs: env: RELEASE_VERSION: ${{ inputs.versionNumber }} steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Get release version run: | # The code below does the following: @@ -34,7 +37,7 @@ jobs: fi echo "RELEASE_VERSION=$RELEASE_VERSION" >> $GITHUB_ENV - name: Update issues related to release - uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/pr-run-linting-check-and-unit-tests.yml b/.github/workflows/pr-run-linting-check-and-unit-tests.yml index 9b76b199f5..7c87fc8abf 100644 --- a/.github/workflows/pr-run-linting-check-and-unit-tests.yml +++ b/.github/workflows/pr-run-linting-check-and-unit-tests.yml @@ -3,6 +3,10 @@ name: On PR code update on: pull_request: types: [opened, synchronize] + +permissions: + contents: read + jobs: run-unit-tests: - uses: ./.github/workflows/reusable-run-linting-check-and-unit-tests.yml \ No newline at end of file + uses: ./.github/workflows/reusable-run-linting-check-and-unit-tests.yml diff --git a/.github/workflows/publish_layer.yml b/.github/workflows/publish_layer.yml index c67d0e58db..067490c197 100644 --- a/.github/workflows/publish_layer.yml +++ b/.github/workflows/publish_layer.yml @@ -1,9 +1,7 @@ name: Deploy layer to all regions permissions: - id-token: write - contents: write - pages: write + contents: read on: # Manual trigger @@ -33,13 +31,13 @@ jobs: if: ${{ (github.event.workflow_run.conclusion == 'success') || (github.event_name == 'workflow_dispatch') }} steps: - name: checkout - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: - fetch-depth: 0 + ref: ${{ github.sha }} - name: Setup Node.js - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: - node-version: "18" + node-version: "20" - name: Setup dependencies uses: ./.github/actions/cached-node-modules - name: CDK build @@ -47,7 +45,7 @@ jobs: - name: Zip output run: zip -r cdk.out.zip layers/cdk.out - name: Archive CDK artifacts - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: cdk-layer-artifact path: cdk.out.zip @@ -57,6 +55,9 @@ jobs: needs: - build-layer uses: ./.github/workflows/reusable_deploy_layer_stack.yml + permissions: + id-token: write + contents: read with: stage: "BETA" artifact-name: "cdk-layer-artifact" @@ -69,6 +70,9 @@ jobs: needs: - deploy-beta uses: ./.github/workflows/reusable_deploy_layer_stack.yml + permissions: + id-token: write + contents: read with: stage: "PROD" artifact-name: "cdk-layer-artifact" @@ -76,31 +80,37 @@ jobs: secrets: target-account-role: ${{ secrets.AWS_LAYERS_PROD_ROLE_ARN }} - prepare_docs_alias: + update_layer_arn_docs: + needs: [deploy-prod] + # Force Github action to run only a single job at a time (based on the group name) + # This is to prevent race-condition and inconsistencies with changelog push + concurrency: + group: changelog-build runs-on: ubuntu-latest permissions: - contents: read - outputs: - DOCS_ALIAS: ${{ steps.set-alias.outputs.DOCS_ALIAS }} + contents: write + pull-requests: write + id-token: none steps: - - name: Set docs alias - id: set-alias + - name: Checkout repository # reusable workflows start clean, so we need to checkout again + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + ref: ${{ github.sha }} + - name: Download CDK layer artifacts + uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 + with: + path: cdk-layer-stack + pattern: cdk-layer-stack-* # merge all Layer artifacts created per region earlier (reusable_deploy_layer_stack.yml; step "Save Layer ARN artifact") + merge-multiple: true + - name: Replace layer versions in documentation run: | - DOCS_ALIAS=latest - if [[ "${{ inputs.pre_release }}" == true ]] ; then - DOCS_ALIAS=alpha - fi - echo DOCS_ALIAS="$DOCS_ALIAS" >> "$GITHUB_OUTPUT" - - release-docs: - needs: [ deploy-prod, prepare_docs_alias ] - permissions: - contents: write - pages: write - id-token: write - secrets: inherit - uses: ./.github/workflows/reusable-publish-docs.yml - with: - version: ${{ inputs.latest_published_version }} - alias: ${{ needs.prepare_docs_alias.outputs.DOCS_ALIAS }} - detached_mode: true + ls -la cdk-layer-stack/ + ./.github/scripts/update_layer_arn.sh cdk-layer-stack + - name: Create PR + id: create-pr + uses: ./.github/actions/create-pr + with: + files: 'docs/index.md' + temp_branch_prefix: 'ci-layer-docs' + pull_request_title: 'chore(ci): update layer ARN on documentation' + github_token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/rebuild-latest-docs.yml b/.github/workflows/rebuild-latest-docs.yml deleted file mode 100644 index 5d6ad78d30..0000000000 --- a/.github/workflows/rebuild-latest-docs.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Rebuild latest docs - -# -# === Documentation hotfix === -# -# 1. Trigger "Rebuild latest docs" workflow manually: https://docs.github.com/en/actions/managing-workflow-runs/manually-running-a-workflow -# 2. Use the latest version released under Releases e.g. 1.6.0 - -on: - workflow_dispatch: - inputs: - latest_published_version: - description: "Latest npm published version to rebuild latest docs for, e.g. 1.6.0" - required: true - -jobs: - release-docs: - permissions: - contents: write - pages: write - id-token: write - secrets: inherit - uses: ./.github/workflows/reusable-publish-docs.yml - with: - version: ${{ inputs.latest_published_version }} - alias: latest \ No newline at end of file diff --git a/.github/workflows/rebuild_latest_docs.yml b/.github/workflows/rebuild_latest_docs.yml new file mode 100644 index 0000000000..717e6b0af2 --- /dev/null +++ b/.github/workflows/rebuild_latest_docs.yml @@ -0,0 +1,37 @@ +name: Rebuild latest docs + +# PROCESS +# +# 1. Build User Guide and API docs +# 2. Publish to GitHub Pages +# 3. Publish to S3 (new home) + +# USAGE +# +# Only used for deploying a documentation hotfix to /latest and its associated version w/o a full release. +# +# Steps: +# +# 1. Trigger "Rebuild latest docs" workflow manually: https://docs.github.com/en/actions/managing-workflow-runs/manually-running-a-workflow +# 2. Use the latest version released under Releases e.g. 2.0.0 + +on: + workflow_dispatch: + inputs: + latest_published_version: + description: "Latest npm published version to rebuild latest docs for, e.g. 1.8.0" + required: true + +permissions: + contents: read + +jobs: + release-docs: + permissions: + id-token: write # trade JWT token for AWS credentials in AWS Docs account + contents: read # read from this repo to publish docs + secrets: inherit + uses: ./.github/workflows/reusable_publish_docs.yml + with: + version: ${{ inputs.latest_published_version }} + alias: latest \ No newline at end of file diff --git a/.github/workflows/record_pr.yml b/.github/workflows/record_pr.yml index 882c54e6ed..33379a1ddd 100644 --- a/.github/workflows/record_pr.yml +++ b/.github/workflows/record_pr.yml @@ -1,22 +1,60 @@ name: Record PR details +# PROCESS +# +# 1. Runs in fork location upon PR creation or changes +# 2. Saves GitHub Pull Request Webhook payload +# 3. Uploads as a temporary GitHub Action Artifact with shortest retention + +# USAGE +# +# see .github/workflows/on_merged_pr.yml and related for full example. +# +# on: +# workflow_run: +# workflows: ["Record PR details"] +# types: +# - completed +# +# Security Note: +# +# For security, this is intended to be a 2-step process: (1) collect PR, (2) act on PR. +# Do not ever use `pull_request_target` to "simplify", as it sends a write-token to the fork. Our linter should catch it. +# +# The first step runs in untrusted location (fork), therefore we limit permissions to only check out code. +# +# The second step will be workflows that want to act on a given PR, this time with intended permissions, and +# it runs on its base location (this repo!). +# +# This enforces zero trust where this workflow always runs on fork with zero permissions on GH_TOKEN. +# When this workflow completes, X workflows run in our repository with the appropriate permissions and sanitize inputs. +# +# Coupled with "Approve GitHub Action to run on forks", we have confidence no privilege can be escalated, +# since any malicious change would need to be approved, and upon social engineering, it'll have zero permissions. + + on: pull_request: - types: [opened, edited, closed] + types: [opened, edited, closed, labeled] + +permissions: + contents: read jobs: record_pr: runs-on: ubuntu-latest - + permissions: + contents: read # NOTE: treat as untrusted location steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: "Extract PR details" - uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: script: | const script = require('.github/scripts/save_pr_details.js') await script({github, context, core}) - - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: pr - path: pr.txt \ No newline at end of file + path: pr.txt + retention-days: 1 \ No newline at end of file diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml index ba50a693ae..1c0617d041 100644 --- a/.github/workflows/release-drafter.yml +++ b/.github/workflows/release-drafter.yml @@ -27,6 +27,6 @@ jobs: permissions: contents: write # create release in draft mode steps: - - uses: release-drafter/release-drafter@65c5fb495d1e69aa8c08a3317bc44ff8aabe9772 # v5.20.1 + - uses: release-drafter/release-drafter@3f0f87098bd6b5c5b9a36d49c41d998ea58f9348 # v5.20.1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/reusable-run-linting-check-and-unit-tests.yml b/.github/workflows/reusable-run-linting-check-and-unit-tests.yml index a8321ad566..d7d7b2bd0a 100644 --- a/.github/workflows/reusable-run-linting-check-and-unit-tests.yml +++ b/.github/workflows/reusable-run-linting-check-and-unit-tests.yml @@ -3,6 +3,9 @@ name: Run unit tests on: workflow_call: +permissions: + contents: read + jobs: run-linting-check-and-unit-tests-on-utilities: runs-on: ubuntu-latest @@ -10,43 +13,43 @@ jobs: NODE_ENV: dev strategy: matrix: - version: [16, 18] + version: [16, 18, 20] fail-fast: false steps: - name: Checkout code - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup NodeJS - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: node-version: ${{ matrix.version }} - cache: 'npm' + cache: "npm" - name: Setup dependencies uses: ./.github/actions/cached-node-modules with: nodeVersion: ${{ matrix.version }} - name: Run linting - run: npm run lint -w packages/commons -w packages/logger -w packages/tracer -w packages/metrics -w packages/parameters -w packages/idempotency -w packages/batch -w packages/parser + run: npm run lint -w packages/commons -w packages/logger -w packages/tracer -w packages/metrics -w packages/parameters -w packages/idempotency -w packages/batch - name: Run unit tests - run: npm t -w packages/commons -w packages/logger -w packages/tracer -w packages/metrics -w packages/parameters -w packages/idempotency -w packages/batch -w packages/parser + run: npm t -w packages/commons -w packages/logger -w packages/tracer -w packages/metrics -w packages/parameters -w packages/idempotency -w packages/batch check-examples: runs-on: ubuntu-latest env: NODE_ENV: dev strategy: matrix: - example: ['sam', 'cdk'] + example: ["sam", "cdk"] fail-fast: false defaults: run: working-directory: examples/${{ matrix.example }} steps: - name: Checkout code - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup NodeJS - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: - node-version: 18 - cache: 'npm' + node-version: 20 + cache: "npm" - name: Setup dependencies uses: ./.github/actions/cached-node-modules - name: Run linting @@ -59,12 +62,12 @@ jobs: NODE_ENV: dev steps: - name: Checkout code - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup NodeJS - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: - node-version: 18 - cache: 'npm' + node-version: 20 + cache: "npm" - name: Setup dependencies uses: ./.github/actions/cached-node-modules - name: Run linting @@ -77,12 +80,12 @@ jobs: NODE_ENV: dev steps: - name: Checkout code - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup NodeJS - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: - node-version: 18 - cache: 'npm' + node-version: 20 + cache: "npm" - name: Setup dependencies uses: ./.github/actions/cached-node-modules - name: Run linting diff --git a/.github/workflows/reusable_deploy_layer_stack.yml b/.github/workflows/reusable_deploy_layer_stack.yml index 88da081792..a4fc08ab17 100644 --- a/.github/workflows/reusable_deploy_layer_stack.yml +++ b/.github/workflows/reusable_deploy_layer_stack.yml @@ -1,9 +1,5 @@ name: Deploy cdk stack -permissions: - id-token: write - contents: read - on: workflow_call: inputs: @@ -23,9 +19,13 @@ on: target-account-role: required: true +permissions: + contents: read jobs: deploy-cdk-stack: + permissions: + id-token: write runs-on: ubuntu-latest strategy: fail-fast: false @@ -49,6 +49,7 @@ jobs: "ap-southeast-3", "ap-southeast-4", "ca-central-1", + "ca-west-1", "eu-west-1", "eu-west-2", "eu-west-3", @@ -61,21 +62,21 @@ jobs: ] steps: - name: checkout - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: aws credentials - uses: aws-actions/configure-aws-credentials@04b98b3f9e85f563fb061be8751a0352327246b0 # v3.0.1 + uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 with: aws-region: ${{ matrix.region }} role-to-assume: ${{ secrets.target-account-role }} mask-aws-account-id: true - name: Setup Node.js - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: - node-version: "18" + node-version: "20" - name: Setup dependencies uses: ./.github/actions/cached-node-modules - name: Download artifact - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 with: name: ${{ inputs.artifact-name }} - name: Unzip artifact @@ -90,19 +91,11 @@ jobs: cat cdk-layer-stack/${{ matrix.region }}-layer-version.txt - name: Save Layer ARN artifact if: ${{ inputs.stage == 'PROD' }} - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: - name: cdk-layer-stack + name: cdk-layer-stack-${{ matrix.region }} path: ./cdk-layer-stack/* # NOTE: upload-artifact does not inherit working-directory setting. if-no-files-found: error retention-days: 1 - name: CDK deploy canary run: npm run cdk -w layers -- deploy --app cdk.out --context region=${{ matrix.region }} 'CanaryStack' --require-approval never --verbose --outputs-file cdk-outputs.json - update_layer_arn_docs: - needs: deploy-cdk-stack - permissions: - contents: write - if: ${{ inputs.stage == 'PROD' }} - uses: ./.github/workflows/reusable_update_layer_arn_docs.yml - with: - latest_published_version: ${{ inputs.latest_published_version }} diff --git a/.github/workflows/reusable_export_pr_details.yml b/.github/workflows/reusable_export_pr_details.yml index 8695b522f2..dc9b44309b 100644 --- a/.github/workflows/reusable_export_pr_details.yml +++ b/.github/workflows/reusable_export_pr_details.yml @@ -1,16 +1,32 @@ name: Export previously recorded PR +# PROCESS +# +# 1. Fetch PR details previously saved from untrusted location +# 2. Parse details for safety +# 3. Export only what's needed for automation, e.g., PR number, title, body, author, action, whether is merged + +# USAGE +# +# see .github/workflows/on_merged_pr.yml and related for full example. +# +# NOTE: meant to be used with workflows that react to a given PR state (labeling, new, merged, etc.) +# done separately to isolate security practices and make it reusable. + on: workflow_call: inputs: record_pr_workflow_id: + description: "Record PR workflow execution ID to download PR details" required: true type: number workflow_origin: # see https://github.com/aws-powertools/powertools-lambda-python/issues/1349 + description: "Repository full name for runner integrity" required: true type: string secrets: token: + description: "GitHub Actions temporary and scoped token" required: true # Map the workflow outputs to job outputs outputs: @@ -32,9 +48,17 @@ on: prIsMerged: description: "Whether PR is merged" value: ${{ jobs.export_pr_details.outputs.prIsMerged }} + prLabels: + description: "PR Labels" + value: ${{ jobs.export_pr_details.outputs.prLabels }} + +permissions: + contents: read jobs: export_pr_details: + permissions: + actions: read # download PR artifact # see https://github.com/aws-powertools/powertools-lambda-python/issues/1349 if: inputs.workflow_origin == 'aws-powertools/powertools-lambda-typescript' runs-on: ubuntu-latest @@ -48,11 +72,12 @@ jobs: prAuthor: ${{ steps.prAuthor.outputs.prAuthor }} prAction: ${{ steps.prAction.outputs.prAction }} prIsMerged: ${{ steps.prIsMerged.outputs.prIsMerged }} + prLabels: ${{ steps.prLabels.outputs.prLabels }} steps: - name: Checkout repository # in case caller workflow doesn't checkout thus failing with file not found - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: "Download previously saved PR" - uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 env: WORKFLOW_ID: ${{ inputs.record_pr_workflow_id }} # For security, we only download artifacts tied to the successful PR recording workflow @@ -84,3 +109,6 @@ jobs: - name: "Export Pull Request Merged status" id: prIsMerged run: echo prIsMerged="$(jq -c '.pull_request.merged' "${FILENAME}")" >> "$GITHUB_OUTPUT" + - name: "Export Pull Request labels" + id: prLabels + run: echo prLabels="$(jq -c '.labels' "${FILENAME}")" >> "$GITHUB_OUTPUT" \ No newline at end of file diff --git a/.github/workflows/reusable-publish-docs.yml b/.github/workflows/reusable_publish_docs.yml similarity index 78% rename from .github/workflows/reusable-publish-docs.yml rename to .github/workflows/reusable_publish_docs.yml index a1d60e3012..3b8fc275d2 100644 --- a/.github/workflows/reusable-publish-docs.yml +++ b/.github/workflows/reusable_publish_docs.yml @@ -1,9 +1,9 @@ name: Reusable Publish docs +# see .github/workflows/on_push_docs.yml for docs + env: - BRANCH: main ORIGIN: aws-powertools/powertools-lambda-typescript - VERSION: "" on: workflow_call: @@ -28,41 +28,43 @@ on: required: false default: false type: boolean + git_ref: + description: "Branch or commit ID to checkout from" + required: false + type: string + default: develop permissions: - contents: write - id-token: write - pages: write + contents: read jobs: - publish-docs: + publish_docs: + if: github.repository == 'aws-powertools/powertools-lambda-typescript' + # Force Github action to run only a single job at a time (based on the group name) + # This is to prevent "race-condition" in publishing a new version of doc to `gh-pages` + concurrency: + group: on-docs-rebuild runs-on: ubuntu-latest environment: Docs + permissions: + id-token: write # trade JWT token for AWS credentials in AWS Docs account steps: - name: Checkout code - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - with: - # While `fetch-depth` is used to allow the workflow to later commit & push the changes. - fetch-depth: 0 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Setup NodeJS - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: - node-version: "18" + node-version: "20" cache: "npm" - name: Setup dependencies uses: ./.github/actions/cached-node-modules - name: Set up Python - uses: actions/setup-python@57ded4d7d5e986d7296eab16560982c6dd7c923b # v4.6.0 + uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0 with: - python-version: "3.8" + python-version: "3.12" - name: Install doc generation dependencies run: | - pip install --upgrade pip - pip install -r docs/requirements.txt - - name: Setup doc deploy - run: | - git config --global user.name Docs deploy - git config --global user.email aws-devax-open-source@amazon.com + pip install --require-hashes -r docs/requirements.txt - name: Git refresh tip (detached mode) # Git Detached mode (release notes) doesn't have origin if: ${{ inputs.detached_mode }} @@ -70,6 +72,8 @@ jobs: git config pull.rebase true git config remote.origin.url >&- || git remote add origin https://github.com/"$ORIGIN" git pull origin "$BRANCH" + env: + BRANCH: ${{ inputs.git_ref }} - name: Normalize Version Number run: echo "VERSION=$(echo ${{ inputs.version }} | sed 's/v//')" >> $GITHUB_ENV - name: Build docs website and API reference @@ -78,15 +82,12 @@ jobs: run: | rm -rf site mkdocs build - # mike deploy --update-aliases --no-redirect ${{ env.VERSION }} ${{ env.ALIAS }} --branch backup-gh-pages - # Set latest version as a default - # mike set-default latest --branch backup-gh-pages - name: Build API docs run: | rm -rf api npm run docs-generateApiDoc - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@04b98b3f9e85f563fb061be8751a0352327246b0 # v3.0.1 + uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 with: aws-region: us-east-1 role-to-assume: ${{ secrets.AWS_DOCS_ROLE_ARN }} @@ -95,7 +96,7 @@ jobs: run: | cp -r api site/ - name: Create Artifact (Site) - uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 + uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 with: name: site path: site diff --git a/.github/workflows/reusable_update_layer_arn_docs.yml b/.github/workflows/reusable_update_layer_arn_docs.yml deleted file mode 100644 index 99fa656e9e..0000000000 --- a/.github/workflows/reusable_update_layer_arn_docs.yml +++ /dev/null @@ -1,52 +0,0 @@ -name: Update Layer ARN Docs - -on: - workflow_call: - inputs: - latest_published_version: - description: "Latest NPM published version to rebuild latest docs for, e.g. 1.5.1" - type: string - required: true - -permissions: - contents: write - -env: - BRANCH: main - -jobs: - publish_layer_arn: - # Force Github action to run only a single job at a time (based on the group name) - # This is to prevent race-condition and inconsistencies with changelog push - concurrency: - group: changelog-build - runs-on: ubuntu-latest - steps: - - name: Checkout repository # reusable workflows start clean, so we need to checkout again - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - with: - fetch-depth: 0 - - name: Git client setup and refresh tip - run: | - git config user.name "Release bot[bot]" - git config user.email "aws-devax-open-source@amazon.com" - git config pull.rebase true - git config remote.origin.url >&- || git remote add origin https://github.com/"${origin}" # Git Detached mode (release notes) doesn't have origin - git pull origin "${BRANCH}" - - name: Download CDK layer artifact - uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 - with: - name: cdk-layer-stack - path: cdk-layer-stack/ - - name: Replace layer versions in documentation - run: | - ls -la cdk-layer-stack/ - ./.github/scripts/update_layer_arn.sh cdk-layer-stack - - name: Update documentation in trunk - run: | - HAS_CHANGE=$(git status --porcelain) - test -z "${HAS_CHANGE}" && echo "Nothing to update" && exit 0 - git add docs/index.md - git commit -m "chore: update layer ARN on documentation" - git pull origin "${BRANCH}" # prevents concurrent branch update failing push - git push origin HEAD:refs/heads/"${BRANCH}" diff --git a/.github/workflows/run-e2e-tests.yml b/.github/workflows/run-e2e-tests.yml index 3db702a2df..9d6b508726 100644 --- a/.github/workflows/run-e2e-tests.yml +++ b/.github/workflows/run-e2e-tests.yml @@ -8,6 +8,9 @@ on: required: false default: '' +permissions: + contents: read + jobs: run-e2e-tests-on-utils: runs-on: ubuntu-latest @@ -28,17 +31,17 @@ jobs: packages/parameters, packages/idempotency, ] - version: [16, 18] + version: [16, 18, 20] arch: [x86_64, arm64] fail-fast: false steps: - name: Checkout Repo - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 # If we pass a PR Number when triggering the workflow we will retrieve the PR info and get its headSHA - name: Extract PR details id: extract_PR_details if: ${{ inputs.prNumber != '' }} - uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6.4.1 + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: script: | const script = require('.github/scripts/get_pr_info.js'); @@ -47,19 +50,19 @@ jobs: # we checkout the PR at that point in time - name: Checkout PR code if: ${{ inputs.prNumber != '' }} - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 with: ref: ${{ steps.extract_PR_details.outputs.headSHA }} - name: Setup NodeJS - uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 + uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: - node-version: ${{ matrix.version }} + node-version: '20' - name: Setup dependencies uses: ./.github/actions/cached-node-modules with: - nodeVersion: ${{ matrix.version }} + nodeVersion: '20' - name: Setup AWS credentials - uses: aws-actions/configure-aws-credentials@04b98b3f9e85f563fb061be8751a0352327246b0 # v3.0.1 + uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 with: role-to-assume: ${{ secrets.AWS_ROLE_ARN_TO_ASSUME }} aws-region: eu-west-1 diff --git a/.github/workflows/secure-workflows.yml b/.github/workflows/secure-workflows.yml new file mode 100644 index 0000000000..c0c1fde8bf --- /dev/null +++ b/.github/workflows/secure-workflows.yml @@ -0,0 +1,37 @@ +name: Lockdown untrusted workflows + +# PROCESS +# +# 1. Scans for any external GitHub Action being used without version pinning (@ vs @v3) +# 2. Scans for insecure practices for inline bash scripts (shellcheck) +# 3. Fail CI and prevent PRs to be merged if any malpractice is found + +# USAGE +# +# Always triggered on new PR, PR changes and PR merge. + + +on: + push: + paths: + - ".github/workflows/**" + pull_request: + paths: + - ".github/workflows/**" + +permissions: + contents: read + +jobs: + enforce_pinned_workflows: + name: Harden Security + runs-on: ubuntu-latest + permissions: + contents: read # checkout code and subsequently GitHub action workflows + steps: + - name: Checkout code + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: Ensure 3rd party workflows have SHA pinned + uses: zgosalvez/github-actions-ensure-sha-pinned-actions@ba37328d4ea95eaf8b3bd6c6cef308f709a5f2ec # v3.0.3 + with: + allowlist: slsa-framework/slsa-github-generator \ No newline at end of file diff --git a/.github/workflows/stale-issues.yml b/.github/workflows/stale-issues.yml index 9e1ad6fca4..d21eda7853 100644 --- a/.github/workflows/stale-issues.yml +++ b/.github/workflows/stale-issues.yml @@ -4,13 +4,16 @@ on: schedule: - cron: "0 0 * * *" +permissions: + contents: read + jobs: check-issues: runs-on: ubuntu-latest permissions: issues: write steps: - - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 # v8.0.0 + - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9.0.0 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-issue-message: "This issue has not received a response in 2 weeks. If you still think there is a problem, please leave a comment to avoid the issue from automatically closing." diff --git a/.gitignore b/.gitignore index 73b53761bc..cb2d901eae 100644 --- a/.gitignore +++ b/.gitignore @@ -49,4 +49,5 @@ site tmp # TS build files -*.tsbuildinfo \ No newline at end of file +tsconfig.tsbuildinfo +.tsbuildinfo \ No newline at end of file diff --git a/.gitpod.Dockerfile b/.gitpod.Dockerfile new file mode 100644 index 0000000000..bee8186bd0 --- /dev/null +++ b/.gitpod.Dockerfile @@ -0,0 +1,16 @@ +# See gitpod image here: https://hub.docker.com/layers/gitpod/workspace-base/latest +FROM gitpod/workspace-base@sha256:d69d08a0e1fa62b6d8db9e7ffe63dc21a58f0242946d945d776a819aec652130 + +USER gitpod + +# Install fnm to manage Node.js versions +RUN curl -fsSL https://fnm.vercel.app/install -o /tmp/install \ + && chmod a+x /tmp/install + && /tmp/install \ + && rm /tmp/install + +# Install AWS SAM CLI +RUN curl -LO https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip \ + && unzip -q aws-sam-cli-linux-x86_64.zip -d sam-installation \ + && sudo ./sam-installation/install \ + && rm -rf sam-installation aws-sam-cli-linux-* diff --git a/.gitpod.yml b/.gitpod.yml index 0591321da9..8cf80f54b6 100644 --- a/.gitpod.yml +++ b/.gitpod.yml @@ -1,13 +1,10 @@ +image: + file: .gitpod.Dockerfile tasks: - init: | # Install Nodejs version specified in .nvmrc - nvm install - nvm use - # Install AWS SAM CLI - wget https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip - unzip aws-sam-cli-linux-x86_64.zip -d sam-installation - sudo ./sam-installation/install - rm -rf sam-installation aws-sam-cli-linux-* + fnm install + fnm use # Install repo dependencies npm run setup-local vscode: @@ -15,4 +12,3 @@ vscode: - dbaeumer.vscode-eslint - esbenp.prettier-vscode - firsttris.vscode-jest-runner - - amazonwebservices.aws-toolkit-vscode \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit index c37466e2b3..d0a778429a 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - npx lint-staged \ No newline at end of file diff --git a/.husky/pre-push b/.husky/pre-push index b5f55642f9..5d325d3caa 100755 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -1,6 +1,3 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - npm t \ -w packages/commons \ -w packages/logger \ diff --git a/.nvmrc b/.nvmrc index a77793ecc5..9de2256827 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -lts/hydrogen +lts/iron diff --git a/CHANGELOG.md b/CHANGELOG.md index 18009a7bc8..0320919dc4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,74 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2.0.2 (2024-03-05) + + +### Bug Fixes + +* **tracer:** modify aws-xray-sdk-core import for js ([#2164](https://github.com/aws-powertools/powertools-lambda-typescript/issues/2164)) ([29630b5](https://github.com/aws-powertools/powertools-lambda-typescript/commit/29630b5b68915ccca1324f3e7ce3e95b85a616be)) + + + + + +## 2.0.1 (2024-03-04) + +**Note:** Version bump only for package aws-lambda-powertools-typescript + + + + + +# [2.0.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.18.1...v2.0.0) (2024-03-04) + +**Note:** Version bump only for package aws-lambda-powertools-typescript + + + + + +## 1.18.1 (2024-02-20) + +**Note:** Version bump only for package aws-lambda-powertools-typescript + + + + + +## [1.18.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.17.0...v1.18.0) (2024-01-26) + +### Features + +**layers:** add `ca-west-1` region ([#1836](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1836)) ([55ff4df](https://github.com/aws-powertools/powertools-lambda-typescript/commit/55ff4df53773e949993c3f21718ea3d447c30f9e)) + +## [1.17.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.16.0...v1.17.0) (2023-11-24) + +**maintenance:** drop support for Node.js 14 ([#1664](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1664)) ([e2a0923](https://github.com/aws-powertools/powertools-lambda-typescript/commit/e2a09232f86167b5208be2daf892aa1ea433ce0f)) + +# [1.16.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.15.0...v1.16.0) (2023-11-16) + +### Features + +- **logger:** add support for `AWS_LAMBDA_LOG_LEVEL` and `POWERTOOLS_LOG_LEVEL` ([#1795](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1795)) ([e69abfb](https://github.com/aws-powertools/powertools-lambda-typescript/commit/e69abfb5f1b5d3bf993ac2fe66fae85a85af9905)) + +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) +- **metrics:** log directly to stdout ([#1786](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1786)) ([75dc5b1](https://github.com/aws-powertools/powertools-lambda-typescript/commit/75dc5b1e16944416a287628c50ec4a0cf82c3023)) + +## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) + +### Bug Fixes + +- **metrics:** deduplicate dimensions when serialising ([#1780](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1780)) ([8181b48](https://github.com/aws-powertools/powertools-lambda-typescript/commit/8181b481ba96fa7a91959ff2d40bdedfe80b451b)) + +## [1.14.1](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.0...v1.14.1) (2023-10-31) + +**Note:** Version bump only for package aws-lambda-powertools-typescript + # [1.14.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.13.1...v1.14.0) (2023-09-29) ### Features diff --git a/README.md b/README.md index 2ff592480d..71a3bb7613 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,11 @@ # Powertools for AWS Lambda (TypeScript) -[![Join our Discord](https://dcbadge.vercel.app/api/server/B8zZKbbyET)](https://discord.gg/B8zZKbbyET) +![NodeSupport](https://img.shields.io/static/v1?label=node&message=%2016|%2018|%2020&color=green?style=flat-square&logo=node) +![GitHub Release](https://img.shields.io/github/v/release/aws-powertools/powertools-lambda-typescript?style=flat-square) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=aws-powertools_powertools-lambda-typescript&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=aws-powertools_powertools-lambda-typescript) +[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=aws-powertools_powertools-lambda-typescript&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=aws-powertools_powertools-lambda-typescript) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/aws-powertools/powertools-lambda-typescript/badge)](https://api.securityscorecards.dev/projects/github.com/aws-powertools/powertools-lambda-typescript) +[![Join our Discord](https://dcbadge.vercel.app/api/server/B8zZKbbyET?style=flat-square)](https://discord.gg/B8zZKbbyET) Powertools for AWS Lambda (TypeScript) is a developer toolkit to implement Serverless [best practices and increase developer velocity](https://docs.powertools.aws.dev/lambda/typescript/latest/#features). @@ -18,7 +23,7 @@ You can use the library in both TypeScript and JavaScript code bases. - [Lambda layers](#lambda-layers) - [NPM modules](#npm-modules) - [Examples](#examples) - - [Serverless TypeScript Demo application](#serverless-typescript-demo-application) + - [Demo applications](#demo-applications) - [Contribute](#contribute) - [Roadmap](#roadmap) - [Connect](#connect) @@ -82,11 +87,13 @@ Or refer to the installation guide of each utility: * [CDK](https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/examples/cdk) * [SAM](https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/examples/sam) -### Serverless TypeScript Demo application +### Demo applications The [Serverless TypeScript Demo](https://github.com/aws-samples/serverless-typescript-demo) shows how to use Powertools for AWS Lambda (TypeScript). You can find instructions on how to deploy and load test this application in the [repository](https://github.com/aws-samples/serverless-typescript-demo). +The [AWS Lambda performance tuning](https://github.com/aws-samples/optimizations-for-lambda-functions) repository also uses Powertools for AWS Lambda (TypeScript) as well as demonstrating other performance tuning techniques for Lambda functions written in TypeScript. + ## Contribute If you are interested in contributing to this project, please refer to our [Contributing Guidelines](https://github.com/aws-powertools/powertools-lambda-typescript/blob/main/CONTRIBUTING.md). @@ -118,6 +125,8 @@ The following companies, among others, use Powertools: * [Sennder](https://sennder.com/) * [Certible](https://www.certible.com/) * [tecRacer GmbH & Co. KG](https://www.tecracer.com/) +* [AppYourself](https://appyourself.net) +* [Alma Media](https://www.almamedia.fi) ### Sharing your work diff --git a/docs/Dockerfile b/docs/Dockerfile index 40c4a3e4b4..878408723b 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -1,2 +1,5 @@ -FROM squidfunk/mkdocs-material -RUN pip install mkdocs-git-revision-date-plugin==0.3.2 mkdocs-exclude==1.0.2 +# version 9.5.2 +FROM squidfunk/mkdocs-material@sha256:3678304a65e17660953a30c0a0be0bc2fb8f55ac450216c14af6ba942badc4dc + +ADD requirements.txt /tmp/ +RUN pip install --require-hashes -r /tmp/requirements.txt \ No newline at end of file diff --git a/docs/contributing/setup.md b/docs/contributing/setup.md index 6960bfcf88..d105488b24 100644 --- a/docs/contributing/setup.md +++ b/docs/contributing/setup.md @@ -23,8 +23,8 @@ graph LR Unless you're using the pre-configured Cloud environment, you'll need the following installed: * [GitHub account](https://github.com/join){target="_blank" rel="nofollow"}. You'll need to be able to fork, clone, and contribute via pull request. -* [Node.js 18.x](https://nodejs.org/download/release/latest-v18.x/){target="_blank" rel="nofollow"}. The repository contains an `.nvmrc` file, so if you use tools like [nvm](https://github.com/nvm-sh/nvm#nvmrc), [fnm](https://github.com/Schniz/fnm) you can switch version quickly. -* [npm 9.x](https://www.npmjs.com/). We use it to install dependencies and manage the workspaces. +* [Node.js 20.x](https://nodejs.org/download/release/latest-v20.x/){target="_blank" rel="nofollow"}. The repository contains an `.nvmrc` file, so if you use tools like [nvm](https://github.com/nvm-sh/nvm#nvmrc), [fnm](https://github.com/Schniz/fnm) you can switch version quickly. +* [npm 10.x](https://www.npmjs.com/). We use it to install dependencies and manage the workspaces. * [Docker](https://docs.docker.com/engine/install/){target="_blank" rel="nofollow"}. We use it to run documentation, and non-JavaScript tooling. * [Fork the repository](https://github.com/aws-powertools/powertools-lambda-typescript/fork). You'll work against your fork of this repository. diff --git a/docs/contributing/testing.md b/docs/contributing/testing.md index 6412297499..0184b095b0 100644 --- a/docs/contributing/testing.md +++ b/docs/contributing/testing.md @@ -84,7 +84,7 @@ To run integration tests you'll need to set up an AWS account and obtain credent * `npm test:e2e -ws` to run all the integration tests for all the modules sequentially * `test:e2e:parallel` to run all the integration tests for all the modules in parallel * `npm test:e2e -w packages/metrics` to run all the integration tests for the `metrics` module -* `npm run test:e2e:nodejs18x -w packages/metrics` to run all the integration tests for the `metrics` module using the `nodejs18x` runtime +* `npm run test:e2e:nodejs20x -w packages/metrics` to run all the integration tests for the `metrics` module using the `nodejs20x` runtime The tests will deploy the necessary AWS resources using AWS CDK, and will run the Lambda functions using the AWS SDK. After that, the tests will verify the Lambda functions behave as expected by checking logs, metrics, traces, and other resources as needed. Finally, the tests will destroy all the AWS resources created at the beginning. diff --git a/docs/core/logger.md b/docs/core/logger.md index 1db08f0839..56aff581fc 100644 --- a/docs/core/logger.md +++ b/docs/core/logger.md @@ -41,17 +41,18 @@ The `Logger` utility must always be instantiated outside the Lambda handler. By ``` ### Utility settings - -The library requires two settings. You can set them as environment variables, or pass them in the constructor. +The library has three optional settings, which can be set via environment variables or passed in the constructor. These settings will be used across all logs emitted: -| Setting | Description | Environment variable | Default Value | Allowed Values | Example Value | Constructor parameter | -| ---------------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------- | ------------------- | ------------------------------------------ | ------------------- | --------------------- | -| **Service name** | Sets the name of service of which the Lambda function is part of, that will be present across all log statements | `POWERTOOLS_SERVICE_NAME` | `service_undefined` | Any string | `serverlessAirline` | `serviceName` | -| **Logging level** | Sets how verbose Logger should be, from the most verbose to the least verbose (no logs) | `LOG_LEVEL` | `info` | `DEBUG`, `INFO`, `WARN`, `ERROR`, `SILENT` | `ERROR` | `logLevel` | -| **Log incoming event** | Whether to log or not the incoming event when using the decorator or middleware | `POWERTOOLS_LOGGER_LOG_EVENT` | `false` | `true`, `false` | `false` | `logEvent` | -| **Debug log sampling** | Probability that a Lambda invocation will print all the log items regardless of the log level setting | `POWERTOOLS_LOGGER_SAMPLE_RATE` | `0` | `0.0` to `1` | `0.5` | `sampleRateValue` | +| Setting | Description | Environment variable | Default Value | Allowed Values | Example Value | Constructor parameter | +| ----------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------- | ------------------- | ------------------------------------------------------ | ------------------- | --------------------- | +| **Service name** | Sets the name of service of which the Lambda function is part of, that will be present across all log statements | `POWERTOOLS_SERVICE_NAME` | `service_undefined` | Any string | `serverlessAirline` | `serviceName` | +| **Logging level** | Sets how verbose Logger should be, from the most verbose to the least verbose (no logs) | `POWERTOOLS_LOG_LEVEL` | `INFO` | `DEBUG`, `INFO`, `WARN`, `ERROR`, `CRITICAL`, `SILENT` | `ERROR` | `logLevel` | +| **Sample rate** | Probability that a Lambda invocation will print all the log items regardless of the log level setting | `POWERTOOLS_LOGGER_SAMPLE_RATE` | `0` | `0.0` to `1.0` | `0.1` | `sampleRateValue` | + +See all environment variables in the [Environment variables](../index.md/#environment-variables) section. +Check API docs to learn more about [Logger constructor options](https://docs.powertools.aws.dev/lambda/typescript/latest/api/types/_aws_lambda_powertools_logger.types.ConstructorOptions.html){target="_blank"}. #### Example using AWS Serverless Application Model (SAM) @@ -68,10 +69,10 @@ These settings will be used across all logs emitted: ShoppingCartApiFunction: Type: AWS::Serverless::Function Properties: - Runtime: nodejs18.x + Runtime: nodejs20.x Environment: Variables: - LOG_LEVEL: WARN + POWERTOOLS_LOG_LEVEL: WARN POWERTOOLS_SERVICE_NAME: serverlessAirline ``` @@ -109,17 +110,18 @@ This functionality will include the following keys in your structured logs: === "Middy Middleware" !!! tip "A note about Middy" - Currently we support only Middy `v3.x` that you can install it by running `npm i @middy/core@~3`. + We guarantee support only for Middy.js `v4.x`, that you can install it by running `npm i @middy/core@~4`. Check their docs to learn more about [Middy and its middleware stack](https://middy.js.org/docs/intro/getting-started){target="_blank"} as well as [best practices when working with Powertools](https://middy.js.org/docs/integrations/lambda-powertools#best-practices){target="_blank"}. - ```typescript hl_lines="1 13" + ```typescript hl_lines="2 14" --8<-- "docs/snippets/logger/middy.ts" ``` === "Decorator" - !!! info - Powertools decorators can only be attached to class methods and follow the experimetal decorators proposal implementation found in TypeScript 4.x. As such, you need to enable the `experimentalDecorators` compiler option in your `tsconfig.json` file to use them. + !!! note + The class method decorators in this project follow the experimental implementation enabled via the [`experimentalDecorators` compiler option](https://www.typescriptlang.org/tsconfig#experimentalDecorators) in TypeScript. Additionally, they are implemented in a way that fits asynchronous methods. When decorating a synchronous method, the decorator replaces its implementation with an asynchronous one causing the caller to have to `await` the now decorated method. + If this is not the desired behavior, you can call the `logger.injectLambdaContext()` method directly in your handler. ```typescript hl_lines="8" --8<-- "docs/snippets/logger/decorator.ts" @@ -129,7 +131,7 @@ This functionality will include the following keys in your structured logs: === "Manual" - ```typescript hl_lines="6" + ```typescript hl_lines="10" --8<-- "docs/snippets/logger/manual.ts" ``` @@ -152,16 +154,16 @@ In each case, the printed log will look like this: } ``` -#### Log incoming event +### Log incoming event -When debugging in non-production environments, you can instruct Logger to log the incoming event with the middleware/decorator parameter `logEvent` or via `POWERTOOLS_LOGGER_LOG_EVENT` env var set to `true`. +When debugging in non-production environments, you can instruct Logger to log the incoming event with the middleware/decorator parameter `logEvent`. ???+ warning This is disabled by default to prevent sensitive info being logged === "Middy Middleware" - ```typescript hl_lines="10" + ```typescript hl_lines="15" --8<-- "docs/snippets/logger/eventMiddy.ts" ``` @@ -173,6 +175,8 @@ When debugging in non-production environments, you can instruct Logger to log th 1. Binding your handler method allows your handler to access `this` within the class methods. +Use `POWERTOOLS_LOGGER_LOG_EVENT` environment variable to enable or disable (`true`/`false`) this feature. + ### Appending persistent additional log keys and values You can append additional persistent keys and values in the logs generated during a Lambda invocation using either mechanism: @@ -232,7 +236,7 @@ If you want to make sure that persistent attributes added **inside the handler f === "Middy Middleware" - ```typescript hl_lines="30" + ```typescript hl_lines="31" --8<-- "docs/snippets/logger/clearStateMiddy.ts" ``` @@ -388,14 +392,13 @@ The error will be logged with default key name `error`, but you can also pass yo !!! tip "Logging errors and log level" You can also log errors using the `warn`, `info`, and `debug` methods. Be aware of the log level though, you might miss those errors when analyzing the log later depending on the log level configuration. - ## Advanced ### Log levels -The default log level is `INFO` and can be set using the `logLevel` constructor option or by using the `LOG_LEVEL` environment variable. +The default log level is `INFO` and can be set using the `logLevel` constructor option or by using the `POWERTOOLS_LOG_LEVEL` environment variable. -Logger supports the following log levels: +We support the following log levels: | Level | Numeric value | | ---------- | ------------- | @@ -420,11 +423,48 @@ The `SILENT` log level provides a simple and efficient way to suppress all log m This feature is useful when you want to have your code instrumented to produce logs, but due to some requirement or business decision, you prefer to not emit them. -By setting the log level to `SILENT`, which can be done either through the `logLevel` constructor option or by using the `LOG_LEVEL` environment variable, you can easily suppress all logs as needed. +By setting the log level to `SILENT`, which can be done either through the `logLevel` constructor option or by using the `POWERTOOLS_LOG_LEVEL` environment variable, you can easily suppress all logs as needed. !!! note Use the `SILENT` log level with care, as it can make it more challenging to monitor and debug your application. Therefore, we advise using this log level judiciously. +#### AWS Lambda Advanced Logging Controls (ALC) + +With [AWS Lambda Advanced Logging Controls (ALC)](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-advanced), you can control the output format of your logs as either `TEXT` or `JSON` and specify the minimum accepted log level for your application. Regardless of the output format setting in Lambda, we will always output JSON formatted logging messages. + +When you have this feature enabled, log messages that don’t meet the configured log level are discarded by Lambda. For example, if you set the minimum log level to `WARN`, you will only receive `WARN` and `ERROR` messages in your AWS CloudWatch Logs, all other log levels will be discarded by Lambda. + +```mermaid +sequenceDiagram + title Lambda ALC allows WARN logs only + participant Lambda service + participant Lambda function + participant Application Logger + + Note over Lambda service: AWS_LAMBDA_LOG_LEVEL="WARN" + Lambda service->>Lambda function: Invoke (event) + Lambda function->>Lambda function: Calls handler + Lambda function->>Application Logger: logger.warn("Something happened") + Lambda function-->>Application Logger: logger.debug("Something happened") + Lambda function-->>Application Logger: logger.info("Something happened") + + Lambda service->>Lambda service: DROP INFO and DEBUG logs + + Lambda service->>CloudWatch Logs: Ingest error logs +``` + +**Priority of log level settings in Powertools for AWS Lambda** + +When the Advanced Logging Controls feature is enabled, we are unable to increase the minimum log level below the `AWS_LAMBDA_LOG_LEVEL` environment variable value, see [AWS Lambda service documentation](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-log-level) for more details. + +We prioritise log level settings in this order: + +1. `AWS_LAMBDA_LOG_LEVEL` environment variable +2. Setting the log level in code using the `logLevel` constructor option, or by calling the `logger.setLogLevel()` method +3. `POWERTOOLS_LOG_LEVEL` environment variable + +In the event you have set a log level in Powertools to a level that is lower than the ACL setting, we will output a warning log message informing you that your messages will be discarded by Lambda. + ### Using multiple Logger instances across your code The `createChild` method allows you to create a child instance of the Logger, which inherits all of the attributes from its parent. You have the option to override any of the settings and attributes from the parent logger, including [its settings](#utility-settings), any [persistent attributes](#appending-persistent-additional-log-keys-and-values), and [the log formatter](#custom-log-formatter-bring-your-own-formatter). Once a child logger is created, the logger and its parent will act as separate instances of the Logger class, and as such any change to one won't be applied to the other. @@ -469,23 +509,21 @@ The `createChild` method allows you to create a child instance of the Logger, wh } ``` -### Sampling logs +### Sampling debug logs -Use sampling when you want to print all the log items generated in your code, based on a **percentage of your concurrent/cold start invocations**. +Use sampling when you want to dynamically change your log level to **DEBUG** based on a **percentage of your concurrent/cold start invocations**. -You can do that by setting a "sample rate", a float value ranging from `0.0` (0%) to `1` (100%), by using a `POWERTOOLS_LOGGER_SAMPLE_RATE` env var or passing the `sampleRateValue` parameter in the Logger constructor. -This number represents the probability that a Lambda invocation will print all the log items regardless of the log level setting. - -For example, by setting the "sample rate" to `0.5`, roughly 50% of your lambda invocations will print all the log items, including the `debug` ones. +You can use values ranging from `0` to `1` (100%) when setting the `sampleRateValue` constructor option or `POWERTOOLS_LOGGER_SAMPLE_RATE` env var. !!! tip "When is this useful?" - In production, to avoid log data pollution and reduce CloudWatch costs, developers are encouraged to use the logger with `logLevel` equal to `ERROR` or `WARN`. - This means that only errors or warnings will be printed. + Let's imagine a sudden spike increase in concurrency triggered a transient issue downstream. When looking into the logs you might not have enough information, and while you can adjust log levels it might not happen again. - However, it might still be useful to print all the logs (including debug ones) of a very small percentage of invocations to have a better understanding of the behaviour of your code in production even when there are no errors. - - **Sampling decision happens at the Logger initialization**. This means sampling may happen significantly more or less than depending on your traffic patterns, for example a steady low number of invocations and thus few cold starts. - If you want to reset the sampling decision and refresh it for each invocation, you can call the `logger.refreshSampleRateCalculation()` method at the beginning or end of your handler. + This feature takes into account transient issues where additional debugging information can be useful. + +Sampling decision happens at the Logger initialization. This means sampling may happen significantly more or less than depending on your traffic patterns, for example a steady low number of invocations and thus few cold starts. + +!!! note + Open a [feature request](https://github.com/aws-powertools/powertools-lambda-typescript/issues/new?assignees=&labels=type%2Ffeature-request%2Ctriage&projects=aws-powertools%2F7&template=feature_request.yml&title=Feature+request%3A+TITLE) if you want Logger to calculate sampling for every invocation === "handler.ts" @@ -599,7 +637,7 @@ You can customize the structure (keys and values) of your log items by passing a === "handler.ts" - ```typescript hl_lines="2 5" + ```typescript hl_lines="2 6" --8<-- "docs/snippets/logger/bringYourOwnFormatterHandler.ts" ``` @@ -660,9 +698,6 @@ This is a Jest sample that provides the minimum information necessary for Logger --8<-- "docs/snippets/logger/unitTesting.ts" ``` -!!! tip - If you don't want to declare your own dummy Lambda Context, you can use [`ContextExamples.helloworldContext`](https://github.com/aws-powertools/powertools-lambda-typescript/blob/main/packages/commons/src/samples/resources/contexts/hello-world.ts#L3-L16) from [`@aws-lambda-powertools/commons`](https://www.npmjs.com/package/@aws-lambda-powertools/commons). - ### Suppress logs with Jest When unit testing your code with [Jest](https://jestjs.io) you can use the `POWERTOOLS_DEV` environment variable in conjunction with the Jest `--silent` CLI option to suppress logs from Logger. diff --git a/docs/core/metrics.md b/docs/core/metrics.md index 925fa6d6cc..83b170f65b 100644 --- a/docs/core/metrics.md +++ b/docs/core/metrics.md @@ -47,6 +47,10 @@ Install the library in your project: npm install @aws-lambda-powertools/metrics ``` +!!! warning "Caution" + + Using the Lambda [Advanced Logging Controls](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-advanced) feature requires you to update your version of Powertools for AWS Lambda (TypeScript) to at least v1.15.0 to ensure metrics are reported correctly to Amazon CloudWatch Metrics. + ### Usage The `Metrics` utility must always be instantiated outside of the Lambda handler. In doing this, subsequent invocations processed by the same instance of your function can reuse these resources. This saves cost by reducing function run time. In addition, `Metrics` can track cold start and emit the appropriate metrics. @@ -88,7 +92,7 @@ The `Metrics` utility is instantiated outside of the Lambda handler. In doing th HelloWorldFunction: Type: AWS::Serverless::Function Properties: - Runtime: nodejs16.x + Runtime: nodejs20.x Environment: Variables: POWERTOOLS_SERVICE_NAME: orders @@ -211,8 +215,9 @@ You can add default dimensions to your metrics by passing them as parameters in === "with logMetrics decorator" - !!! info - Powertools decorators can only be attached to class methods and follow the experimetal decorators proposal implementation found in TypeScript 4.x. As such, you need to enable the `experimentalDecorators` compiler option in your `tsconfig.json` file to use them. + !!! note + The class method decorators in this project follow the experimental implementation enabled via the [`experimentalDecorators` compiler option](https://www.typescriptlang.org/tsconfig#experimentalDecorators) in TypeScript. Additionally, they are implemented in a way that fits asynchronous methods. When decorating a synchronous method, the decorator replaces its implementation with an asynchronous one causing the caller to have to `await` the now decorated method. + If this is not the desired behavior, you can use the `logMetrics` middleware instead. ```typescript hl_lines="12" --8<-- "docs/snippets/metrics/defaultDimensionsDecorator.ts" @@ -248,7 +253,7 @@ See below an example of how to automatically flush metrics with the Middy-compat === "handler.ts" - ```typescript hl_lines="20" + ```typescript hl_lines="2 17" --8<-- "docs/snippets/metrics/middy.ts" ``` @@ -276,9 +281,9 @@ See below an example of how to automatically flush metrics with the Middy-compat #### Using the class decorator -!!! info - Decorators can only be attached to a class declaration, method, accessor, property, or parameter. Therefore, if you prefer to write your handler as a standard function rather than a Class method, check the [middleware](#using-a-middleware) or [manual](#manually) method sections instead. - See the [official TypeScript documentation](https://www.typescriptlang.org/docs/handbook/decorators.html) for more details. +!!! note + The class method decorators in this project follow the experimental implementation enabled via the [`experimentalDecorators` compiler option](https://www.typescriptlang.org/tsconfig#experimentalDecorators) in TypeScript. Additionally, they are implemented in a way that fits asynchronous methods. When decorating a synchronous method, the decorator replaces its implementation with an asynchronous one causing the caller to have to `await` the now decorated method. + If this is not the desired behavior, you can use the `logMetrics` middleware instead. The `logMetrics` decorator of the metrics utility can be used when your Lambda handler function is implemented as method of a Class. @@ -363,7 +368,7 @@ You can optionally capture cold start metrics with the `logMetrics` middleware o === "Middy Middleware" - ```typescript hl_lines="21" + ```typescript hl_lines="18" --8<-- "docs/snippets/metrics/captureColdStartMetricMiddy.ts" ``` @@ -393,7 +398,7 @@ You can add high-cardinality data as part of your Metrics log with the `addMetad === "handler.ts" - ```typescript hl_lines="18" + ```typescript hl_lines="15" --8<-- "docs/snippets/metrics/addMetadata.ts" ``` diff --git a/docs/core/tracer.md b/docs/core/tracer.md index c8dab4003c..2c45e0faad 100644 --- a/docs/core/tracer.md +++ b/docs/core/tracer.md @@ -22,7 +22,7 @@ Tracer is an opinionated thin wrapper for [AWS X-Ray SDK for Node.js](https://gi ## Getting started -!!! note "Tracer relies on AWS X-Ray SDK over [OpenTelememetry Distro (ADOT)](https://aws-otel.github.io/docs/getting-started/lambda){target="_blank"} for optimal cold start (lower latency)." +!!! note "Tracer relies on AWS X-Ray SDK over [OpenTelemetry Distro (ADOT)](https://aws-otel.github.io/docs/getting-started/lambda){target="_blank"} for optimal cold start (lower latency)." ### Installation @@ -74,7 +74,7 @@ The `Tracer` utility is instantiated outside of the Lambda handler. In doing thi HelloWorldFunction: Type: AWS::Serverless::Function Properties: - Runtime: nodejs18.x + Runtime: nodejs20.x Tracing: Active Environment: Variables: @@ -88,17 +88,18 @@ You can quickly start by importing the `Tracer` class, initialize it outside the === "Middy Middleware" !!! tip "A note about Middy" - Currently we support only Middy `v3.x` that you can install it by running `npm i @middy/core@~3`. + We guarantee support only for Middy.js `v4.x`, that you can install it by running `npm i @middy/core@~4`. Check their docs to learn more about [Middy and its middleware stack](https://middy.js.org/docs/intro/getting-started){target="_blank"} as well as [best practices when working with Powertools](https://middy.js.org/docs/integrations/lambda-powertools#best-practices){target="_blank"}. - ```typescript hl_lines="1 14 16" + ```typescript hl_lines="2 15 17" --8<-- "docs/snippets/tracer/middy.ts" ``` === "Decorator" - !!! info - Powertools decorators can only be attached to class methods and follow the experimetal decorators proposal implementation found in TypeScript 4.x. As such, you need to enable the `experimentalDecorators` compiler option in your `tsconfig.json` file to use them. + !!! note + The class method decorators in this project follow the experimental implementation enabled via the [`experimentalDecorators` compiler option](https://www.typescriptlang.org/tsconfig#experimentalDecorators) in TypeScript. Additionally, they are implemented in a way that fits asynchronous methods. When decorating a synchronous method, the decorator replaces its implementation with an asynchronous one causing the caller to have to `await` the now decorated method. + If this is not the desired behavior, you can use one of the other patterns instead. ```typescript hl_lines="8" --8<-- "docs/snippets/tracer/decorator.ts" @@ -152,10 +153,14 @@ When using the `captureLambdaHandler` decorator or middleware, Tracer performs t ### Methods -You can trace other Class methods using the `captureMethod` decorator or any arbitrary function using manual instrumentation. +You can trace other class methods using the `captureMethod` decorator or any arbitrary asynchronous function using manual instrumentation. === "Decorator" + !!! note + The class method decorators in this project follow the experimental implementation enabled via the [`experimentalDecorators` compiler option](https://www.typescriptlang.org/tsconfig#experimentalDecorators) in TypeScript. Additionally, they are implemented in a way that fits asynchronous methods. When decorating a synchronous method, the decorator replaces its implementation with an asynchronous one causing the caller to have to `await` the now decorated method. + If this is not the desired behavior, you can use manual instrumentation instead. + ```typescript hl_lines="8" --8<-- "docs/snippets/tracer/captureMethodDecorator.ts" ``` @@ -181,7 +186,7 @@ You can patch any AWS SDK clients by calling the `captureAWSv3Client` method: === "index.ts" - ```typescript hl_lines="5" + ```typescript hl_lines="6" --8<-- "docs/snippets/tracer/captureAWSv3.ts" ``` @@ -192,7 +197,7 @@ You can patch all AWS SDK v2 clients by calling the `captureAWS` method: === "index.ts" - ```typescript hl_lines="5" + ```typescript hl_lines="7" --8<-- "docs/snippets/tracer/captureAWSAll.ts" ``` @@ -200,7 +205,7 @@ If you're looking to shave a few microseconds, or milliseconds depending on your === "index.ts" - ```typescript hl_lines="5" + ```typescript hl_lines="6" --8<-- "docs/snippets/tracer/captureAWS.ts" ``` @@ -263,7 +268,7 @@ Use **`POWERTOOLS_TRACER_CAPTURE_RESPONSE=false`** environment variable to instr 2. You might manipulate **streaming objects that can be read only once**; this prevents subsequent calls from being empty 3. You might return **more than 64K** of data _e.g., `message too long` error_ -Alternatively, use the `captureResponse: false` option in both `tracer.captureLambdaHandler()` and `tracer.captureMethod()` decorators, or use the same option in the Middy `captureLambdaHander` middleware to instruct Tracer **not** to serialize function responses as metadata. +Alternatively, use the `captureResponse: false` option in both `tracer.captureLambdaHandler()` and `tracer.captureMethod()` decorators, or use the same option in the Middy `captureLambdaHandler` middleware to instruct Tracer **not** to serialize function responses as metadata. === "method.ts" @@ -279,7 +284,7 @@ Alternatively, use the `captureResponse: false` option in both `tracer.captureLa === "middy.ts" - ```typescript hl_lines="17" + ```typescript hl_lines="18" --8<-- "docs/snippets/tracer/disableCaptureResponseMiddy.ts" ``` diff --git a/docs/index.md b/docs/index.md index e0c5b30e35..c8e7497aab 100644 --- a/docs/index.md +++ b/docs/index.md @@ -26,7 +26,7 @@ You can use Powertools for AWS Lambda (TypeScript) in both TypeScript and JavaSc You can install Powertools for AWS Lambda (TypeScript) using one of the following options: -* **Lambda Layer**: [**arn:aws:lambda:{region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:21**](#){: .copyMe}:clipboard: +* **Lambda Layer**: [**arn:aws:lambda:{region}:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2**](#){: .copyMe}:clipboard: * **npm**: [`npm install @aws-lambda-powertools/tracer @aws-lambda-powertools/metrics @aws-lambda-powertools/logger`](#){: .copyMe}:clipboard: ### Lambda Layer @@ -39,34 +39,35 @@ You can include Powertools for AWS Lambda (TypeScript) Lambda Layer using [AWS L ??? note "Click to expand and copy any regional Lambda Layer ARN" - | Region | Layer ARN | - | ---------------- | ------------------------------------------------------------------------------------------------------------ | - | `us-east-1` | [arn:aws:lambda:us-east-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `us-east-2` | [arn:aws:lambda:us-east-2:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `us-west-1` | [arn:aws:lambda:us-west-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `us-west-2` | [arn:aws:lambda:us-west-2:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `ap-south-1` | [arn:aws:lambda:ap-south-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `ap-east-1` | [arn:aws:lambda:ap-east-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `ap-northeast-2` | [arn:aws:lambda:ap-northeast-2:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `ap-northeast-3` | [arn:aws:lambda:ap-northeast-3:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `ap-southeast-1` | [arn:aws:lambda:ap-southeast-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `ap-southeast-2` | [arn:aws:lambda:ap-southeast-2:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `ap-southeast-3` | [arn:aws:lambda:ap-southeast-3:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `ap-southeast-4` | [arn:aws:lambda:ap-southeast-4:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `eu-central-1` | [arn:aws:lambda:eu-central-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `eu-central-2` | [arn:aws:lambda:eu-central-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `eu-west-1` | [arn:aws:lambda:eu-west-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `eu-west-2` | [arn:aws:lambda:eu-west-2:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `eu-west-3` | [arn:aws:lambda:eu-west-3:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `eu-north-1` | [arn:aws:lambda:eu-north-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `eu-south-1` | [arn:aws:lambda:eu-south-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `eu-south-2` | [arn:aws:lambda:eu-south-2:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `ca-central-1` | [arn:aws:lambda:ca-central-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `sa-east-1` | [arn:aws:lambda:sa-east-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `af-south-1` | [arn:aws:lambda:af-south-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `me-south-1` | [arn:aws:lambda:me-south-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | - | `il-central-1` | [arn:aws:lambda:il-central-1:094274105915:layer:AWSLambdaPowertoolsTypeScript:21](#){: .copyMe}:clipboard: | + | Region | Layer ARN | + | ---------------- | ------------------------------------------------------------------------------------------------------------- | + | `us-east-1` | [arn:aws:lambda:us-east-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `us-east-2` | [arn:aws:lambda:us-east-2:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `us-west-1` | [arn:aws:lambda:us-west-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `us-west-2` | [arn:aws:lambda:us-west-2:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `ap-south-1` | [arn:aws:lambda:ap-south-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `ap-east-1` | [arn:aws:lambda:ap-east-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `ap-northeast-1` | [arn:aws:lambda:ap-northeast-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `ap-northeast-2` | [arn:aws:lambda:ap-northeast-2:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `ap-northeast-3` | [arn:aws:lambda:ap-northeast-3:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `ap-southeast-1` | [arn:aws:lambda:ap-southeast-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `ap-southeast-2` | [arn:aws:lambda:ap-southeast-2:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `ap-southeast-3` | [arn:aws:lambda:ap-southeast-3:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `ap-southeast-4` | [arn:aws:lambda:ap-southeast-4:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `eu-central-1` | [arn:aws:lambda:eu-central-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `eu-central-2` | [arn:aws:lambda:eu-central-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `eu-west-1` | [arn:aws:lambda:eu-west-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `eu-west-2` | [arn:aws:lambda:eu-west-2:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `eu-west-3` | [arn:aws:lambda:eu-west-3:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `eu-north-1` | [arn:aws:lambda:eu-north-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `eu-south-1` | [arn:aws:lambda:eu-south-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `eu-south-2` | [arn:aws:lambda:eu-south-2:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `ca-central-1` | [arn:aws:lambda:ca-central-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `ca-west-1` | [arn:aws:lambda:ca-west-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `sa-east-1` | [arn:aws:lambda:sa-east-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `af-south-1` | [arn:aws:lambda:af-south-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `me-south-1` | [arn:aws:lambda:me-south-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | + | `il-central-1` | [arn:aws:lambda:il-central-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2](#){: .copyMe}:clipboard: | ??? note "Click to expand and copy code snippets for popular frameworks" @@ -77,7 +78,7 @@ You can include Powertools for AWS Lambda (TypeScript) Lambda Layer using [AWS L Type: AWS::Serverless::Function Properties: Layers: - - !Sub arn:aws:lambda:${AWS::Region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:21 + - !Sub arn:aws:lambda:${AWS::Region}:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2 ``` If you use `esbuild` to bundle your code, make sure to exclude `@aws-lambda-powertools` from being bundled since the packages will be already present the Layer: @@ -108,7 +109,7 @@ You can include Powertools for AWS Lambda (TypeScript) Lambda Layer using [AWS L hello: handler: lambda_function.lambda_handler layers: - - arn:aws:lambda:${aws:region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:21 + - arn:aws:lambda:${aws:region}:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2 ``` If you use `esbuild` to bundle your code, make sure to exclude `@aws-lambda-powertools` from being bundled since the packages will be already present the Layer: @@ -140,7 +141,7 @@ You can include Powertools for AWS Lambda (TypeScript) Lambda Layer using [AWS L const powertoolsLayer = lambda.LayerVersion.fromLayerVersionArn( this, 'PowertoolsLayer', - `arn:aws:lambda:${cdk.Stack.of(this).region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:21` + `arn:aws:lambda:${cdk.Stack.of(this).region}:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2` ); new lambda.Function(this, 'Function', { @@ -192,7 +193,7 @@ You can include Powertools for AWS Lambda (TypeScript) Lambda Layer using [AWS L role = ... handler = "index.handler" runtime = "nodejs16.x" - layers = ["arn:aws:lambda:{aws::region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:21"] + layers = ["arn:aws:lambda:{aws::region}:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2"] source_code_hash = filebase64sha256("lambda_function_payload.zip") } ``` @@ -210,7 +211,7 @@ You can include Powertools for AWS Lambda (TypeScript) Lambda Layer using [AWS L const lambdaFunction = new aws.lambda.Function('function', { layers: [ - pulumi.interpolate`arn:aws:lambda:${aws.getRegionOutput().name}:094274105915:layer:AWSLambdaPowertoolsTypeScript:21` + pulumi.interpolate`arn:aws:lambda:${aws.getRegionOutput().name}:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2` ], code: new pulumi.asset.FileArchive('lambda_function_payload.zip'), tracingConfig: { @@ -234,7 +235,7 @@ You can include Powertools for AWS Lambda (TypeScript) Lambda Layer using [AWS L ? Do you want to configure advanced settings? Yes ... ? Do you want to enable Lambda layers for this function? Yes - ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:{aws::region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:21 + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:{aws::region}:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2 ❯ amplify push -y # Updating an existing function and add the layer @@ -244,7 +245,7 @@ You can include Powertools for AWS Lambda (TypeScript) Lambda Layer using [AWS L - Name: ? Which setting do you want to update? Lambda layers configuration ? Do you want to enable Lambda layers for this function? Yes - ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:{aws::region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:21 + ? Enter up to 5 existing Lambda layer ARNs (comma-separated): arn:aws:lambda:{aws::region}:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2 ? Do you want to edit the local lambda function now? No ``` @@ -254,7 +255,7 @@ You can include Powertools for AWS Lambda (TypeScript) Lambda Layer using [AWS L Change {region} to your AWS region, e.g. `eu-west-1` ```bash title="AWS CLI" - aws lambda get-layer-version-by-arn --arn arn:aws:lambda:{aws::region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:21 --region {region} + aws lambda get-layer-version-by-arn --arn arn:aws:lambda:{aws::region}:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:2 --region {region} ``` The pre-signed URL to download this Lambda Layer will be within `Location` key. @@ -276,7 +277,8 @@ The project's repository includes examples of how to instrument your functions b * [AWS CDK](https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/examples/cdk){target="_blank"} * [AWS SAM](https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/examples/sam){target="_blank"} -If instead you want to see Powertools for AWS Lambda (TypeScript) in a slightly more complex use case, check the [Serverless TypeScript Demo](https://github.com/aws-samples/serverless-typescript-demo). You can find instructions on how to deploy and load test this application in the [repository](https://github.com/aws-samples/serverless-typescript-demo). +If instead you want to see Powertools for AWS Lambda (TypeScript) in a slightly more complex use case, check the [Serverless TypeScript Demo](https://github.com/aws-samples/serverless-typescript-demo) or the [AWS Lambda performance tuning](https://github.com/aws-samples/optimizations-for-lambda-functions) repository. Both demos use Powertools for AWS Lambda (TypeScript) as well as demonstrating other common techniques for Lambda functions written in TypeScript. + ## Features @@ -307,7 +309,7 @@ Core utilities such as Tracing, Logging, and Metrics will be available across al | **POWERTOOLS_LOGGER_LOG_EVENT** | Log incoming event | [Logger](core/logger.md) | `false` | | **POWERTOOLS_LOGGER_SAMPLE_RATE** | Debug log sampling | [Logger](core/logger.md) | `0` | | **POWERTOOLS_DEV** | Increase JSON indentation to ease debugging when running functions locally or in a non-production environment | [Logger](core/logger.md) | `false` | -| **LOG_LEVEL** | Set logging level | [Logger](core/logger.md) | `INFO` | +| **POWERTOOLS_LOG_LEVEL** | Sets how verbose Logger should be, from the most verbose to the least verbose (no logs) | [Logger](core/logger.md) | `INFO` | | **POWERTOOLS_PARAMETERS_MAX_AGE** | Adjust how long values are kept in cache (in seconds) | [Parameters](utilities/parameters.md) | `5` | | **POWERTOOLS_PARAMETERS_SSM_DECRYPT** | Set whether to decrypt or not values retrieved from AWS Systems Manager Parameters Store | [Parameters](utilities/parameters.md) | `false` | | **POWERTOOLS_IDEMPOTENCY_DISABLED** | Disable the Idempotency logic without changing your code, useful for testing | [Idempotency](utilities/idempotency.md) | `false` | @@ -331,6 +333,8 @@ The following companies, among others, use Powertools: * [Sennder](https://sennder.com/){target="_blank"} * [Certible](https://www.certible.com/){target="_blank"} * [tecRacer GmbH & Co. KG](https://www.tecracer.com/){target="_blank"} +* [AppYourself](https://appyourself.net){target="_blank"} +* [Alma Media](https://www.almamedia.fi){target="_blank"} ### Sharing your work diff --git a/docs/maintainers.md b/docs/maintainers.md index d5608f1ac8..fd8480f687 100644 --- a/docs/maintainers.md +++ b/docs/maintainers.md @@ -33,59 +33,59 @@ Previous active maintainers who contributed to this project. These are the most common labels used by maintainers to triage issues, pull requests (PR), and for project management: -| Label | Usage | Notes | -| -------------------------------------- | ---------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | -| triage | New issues that require maintainers review | Issue template | -| area/documentation | Improvements or additions to documentation | Examples/Readme files; Doc additions, fixes, etc.; | -| area/logger | Items related to the Logger Utility | PR automation | -| area/metrics | Items related to the Metrics Utility | PR automation | -| area/tracer | Items related to the Tracer Utility | PR automation | -| area/idempotency | Items related to the Idempotency Utility | PR automation | -| area/parameters | Items related to the Parameters Utility | PR automation | -| area/commons | Items related to the Commons Utility | PR automation | -| area/jmespath | Items related to the JMESPath Utility | PR automation | -| area/validation | Items related to the Validation Utility | PR automation | -| area/batch | Items related to the Batch Processing Utility | PR automation | -| area/parser | Items related to the Parser Utility | PR automation | -| area/automation | Items related to automation like GitHub workflows or CI/CD | PR automation | -| area/layers | Items related to the Lambda Layers pipeline | PR automation | -| size/XS | PRs between 0-9 LOC | PR automation | -| size/S | PRs between 10-29 LOC | PR automation | -| size/M | PRs between 30-99 LOC | PR automation | -| size/L | PRs between 100-499 LOC | PR automation | -| size/XL | PRs between 500-999 LOC, often PRs that grown with feedback | PR automation | -| size/XXL | PRs with 1K+ LOC, largely documentation related | PR automation | -| customer-reference | Authorization to use company name in our documentation | Public Relations | -| community-content | Suggested content to feature in our documentation | Public Relations | -| do-not-merge | PRs that are blocked for varying reasons | Timeline is uncertain | -| type/bug | Unexpected, reproducible and unintended software behavior | PR/Release automation; Doc snippets are excluded; | -| type/bug-upstream | Bug caused by upstream dependency | | -| type/not-a-bug | New and existing bug reports incorrectly submitted as bug | Analytics | -| type/deprecation | This item contains code deprecation | | -| type/duplicate | This issue is a duplicate of an existing one | Analytics | -| type/feature-request | Issue requesting new or enhancements to existing features | Issue template | -| type/feature | PRs that introduce new features | PR automation | -| type/enhancement | PRs that introduce minor changes, usually to existing features | PR automation | -| type/RFC | Technical design documents related to a feature request | | -| type/internal | PRs that introduce changes in governance, tech debt and chores (linting setup, baseline, etc.) | PR automation | -| type/tests | PRs that add or change tests | PR automation | -| type/dependencies | Changes that touch dependencies, e.g. Dependabot, etc. | Issues/PR automation | -| type/breaking-change | Changes that will cause customer impact and need careful triage | | -| status/blocked | Items which progress is blocked by external dependency or reason | | -| status/confirmed | Items with clear scope and that are ready for implementation | | -| status/discussing | Items that need to be discussed, elaborated, or refined | | -| status/on-hold | Items that are on hold and will be revisited in the future | | -| status/pending-release | Merged changes that will be available soon | Release automation auto-closes/notifies it | -| status/completed | Items that are complete and have been merged and/or shipped | | -| status/rejected | This is something we will not be working on. At least, not in the measurable future | | -| status/pending-close-response-required | This issue will be closed soon unless the discussion moves forward | Stale Automation | -| revisit-in-3-months | Blocked issues/PRs that need to be revisited | Often releated to `need-customer-feedback`, prioritization, etc. | -| good-first-issue | Something that is suitable for those who want to start contributing | | -| help-wanted | Tasks you want help from anyone to move forward | Bandwidth, complex topics, etc. | -| need-customer-feedback | Tasks that need more feedback before proceeding | 80/20% rule, uncertain, etc. | -| need-more-information | Missing information before making any calls | Signal that investigation or answers are needed | -| need-response | Requires a response from a customer and might be automatically closed if none is received | Marked as stale after 2 weeks, and closed after 3 | -| need-issue | PR is missing a related issue for tracking change | | +| Label | Usage | Notes | +| -------------------------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | +| triage | New issues that require maintainers review | Issue template | +| area/documentation | Improvements or additions to documentation | Examples/Readme files; Doc additions, fixes, etc.; | +| area/logger | Items related to the Logger Utility | PR automation | +| area/metrics | Items related to the Metrics Utility | PR automation | +| area/tracer | Items related to the Tracer Utility | PR automation | +| area/idempotency | Items related to the Idempotency Utility | PR automation | +| area/parameters | Items related to the Parameters Utility | PR automation | +| area/commons | Items related to the Commons Utility | PR automation | +| area/jmespath | Items related to the JMESPath Utility | PR automation | +| area/validation | Items related to the Validation Utility | PR automation | +| area/batch | Items related to the Batch Processing Utility | PR automation | +| area/parser | Items related to the Parser Utility | PR automation | +| area/automation | Items related to automation like GitHub workflows or CI/CD | PR automation | +| area/layers | Items related to the Lambda Layers pipeline | PR automation | +| size/XS | PRs between 0-9 LOC | PR automation | +| size/S | PRs between 10-29 LOC | PR automation | +| size/M | PRs between 30-99 LOC | PR automation | +| size/L | PRs between 100-499 LOC | PR automation | +| size/XL | PRs between 500-999 LOC, often PRs that grown with feedback | PR automation | +| size/XXL | PRs with 1K+ LOC, largely documentation related | PR automation | +| customer-reference | Authorization to use company name in our documentation | Public Relations | +| community-content | Suggested content to feature in our documentation | Public Relations | +| do-not-merge | PRs that are blocked for varying reasons | Timeline is uncertain | +| type/bug | Unexpected, reproducible and unintended software behavior | PR/Release automation; Doc snippets are excluded; | +| type/bug-upstream | Bug caused by upstream dependency | | +| type/not-a-bug | New and existing bug reports incorrectly submitted as bug | Analytics | +| type/deprecation | This item contains code deprecation | | +| type/duplicate | This issue is a duplicate of an existing one | Analytics | +| type/feature-request | Issue requesting new or enhancements to existing features | Issue template | +| type/feature | PRs that introduce new features | PR automation | +| type/enhancement | PRs that introduce minor changes, usually to existing features | PR automation | +| type/RFC | Technical design documents related to a feature request | | +| type/internal | PRs that introduce changes in governance, tech debt and chores (linting setup, baseline, etc.) | PR automation | +| type/tests | PRs that add or change tests | PR automation | +| type/dependencies | Changes that touch dependencies, e.g. Dependabot, etc. | Issues/PR automation | +| type/breaking-change | Changes that will cause customer impact and need careful triage | | +| status/blocked | Items which progress is blocked by external dependency or reason | | +| status/confirmed | Items with clear scope and that are ready for implementation | | +| status/discussing | Items that need to be discussed, elaborated, or refined | | +| status/on-hold | Items that are on hold and will be revisited in the future | | +| status/pending-release | Merged changes that will be available soon | Release automation auto-closes/notifies it | +| status/completed | Items that are complete and have been merged and/or shipped | | +| status/rejected | This is something we will not be working on. At least, not in the measurable future | | +| status/pending-close-response-required | This issue will be closed soon unless the discussion moves forward | Stale Automation | +| revisit-in-3-months | Blocked issues/PRs that need to be revisited | Often related to `need-customer-feedback`, prioritization, etc. | +| good-first-issue | Something that is suitable for those who want to start contributing | | +| help-wanted | Tasks you want help from anyone to move forward | Bandwidth, complex topics, etc. | +| need-customer-feedback | Tasks that need more feedback before proceeding | 80/20% rule, uncertain, etc. | +| need-more-information | Missing information before making any calls | Signal that investigation or answers are needed | +| need-response | Requires a response from a customer and might be automatically closed if none is received | Marked as stale after 2 weeks, and closed after 3 | +| need-issue | PR is missing a related issue for tracking change | | ## Maintainer Responsibilities @@ -160,7 +160,7 @@ Some examples using our initial and new RFC templates: [#447](https://github.com ### Releasing a new version -Firstly, make sure all the PRs that you want to include in the release are merged into the `main` banch. +Firstly, make sure all the PRs that you want to include in the release are merged into the `main` branch. Next, run the integration tests one last time to make sure everything is working as expected. See [Run end to end tests](#run-end-to-end-tests) for more details. diff --git a/docs/media/logos/appyourself.svg b/docs/media/logos/appyourself.svg new file mode 100644 index 0000000000..d3417fc0f5 --- /dev/null +++ b/docs/media/logos/appyourself.svg @@ -0,0 +1,43 @@ + + + + diff --git a/docs/overrides/main.html b/docs/overrides/main.html index 0d556b6813..21efa64b87 100644 --- a/docs/overrides/main.html +++ b/docs/overrides/main.html @@ -5,4 +5,9 @@ Click here to go to latest. +{% endblock %} + +{% block announce %} +Version 2 is coming soon 🔥 Check out the upgrade guide to see +what's new. {% endblock %} \ No newline at end of file diff --git a/docs/requirements.in b/docs/requirements.in new file mode 100644 index 0000000000..39c871114f --- /dev/null +++ b/docs/requirements.in @@ -0,0 +1,4 @@ +mike==1.1.2 +mkdocs-material==9.5.12 +mkdocs-git-revision-date-plugin==0.3.2 +mkdocs-exclude==1.0.2 \ No newline at end of file diff --git a/docs/requirements.txt b/docs/requirements.txt index 7806a7e916..2da9bfcd0b 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,4 +1,465 @@ -mike==1.1.2 -mkdocs-material==9.4.6 -mkdocs-git-revision-date-plugin==0.3.2 -mkdocs-exclude==1.0.2 \ No newline at end of file +# +# This file is autogenerated by pip-compile with Python 3.11 +# by the following command: +# +# pip-compile --generate-hashes --output-file=requirements.txt requirements.in +# +babel==2.14.0 \ + --hash=sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363 \ + --hash=sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287 + # via mkdocs-material +certifi==2023.11.17 \ + --hash=sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1 \ + --hash=sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474 + # via requests +charset-normalizer==3.3.2 \ + --hash=sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027 \ + --hash=sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087 \ + --hash=sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786 \ + --hash=sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8 \ + --hash=sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09 \ + --hash=sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185 \ + --hash=sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574 \ + --hash=sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e \ + --hash=sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519 \ + --hash=sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898 \ + --hash=sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269 \ + --hash=sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3 \ + --hash=sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f \ + --hash=sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6 \ + --hash=sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8 \ + --hash=sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a \ + --hash=sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73 \ + --hash=sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc \ + --hash=sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714 \ + --hash=sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2 \ + --hash=sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc \ + --hash=sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce \ + --hash=sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d \ + --hash=sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e \ + --hash=sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6 \ + --hash=sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269 \ + --hash=sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 \ + --hash=sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d \ + --hash=sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a \ + --hash=sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4 \ + --hash=sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 \ + --hash=sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d \ + --hash=sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0 \ + --hash=sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed \ + --hash=sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068 \ + --hash=sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac \ + --hash=sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25 \ + --hash=sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 \ + --hash=sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab \ + --hash=sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26 \ + --hash=sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2 \ + --hash=sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db \ + --hash=sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f \ + --hash=sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5 \ + --hash=sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99 \ + --hash=sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c \ + --hash=sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d \ + --hash=sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811 \ + --hash=sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa \ + --hash=sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a \ + --hash=sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03 \ + --hash=sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b \ + --hash=sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04 \ + --hash=sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c \ + --hash=sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001 \ + --hash=sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458 \ + --hash=sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389 \ + --hash=sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99 \ + --hash=sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985 \ + --hash=sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537 \ + --hash=sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238 \ + --hash=sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f \ + --hash=sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d \ + --hash=sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796 \ + --hash=sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a \ + --hash=sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143 \ + --hash=sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8 \ + --hash=sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c \ + --hash=sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5 \ + --hash=sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5 \ + --hash=sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711 \ + --hash=sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4 \ + --hash=sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6 \ + --hash=sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c \ + --hash=sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7 \ + --hash=sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4 \ + --hash=sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b \ + --hash=sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae \ + --hash=sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12 \ + --hash=sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c \ + --hash=sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae \ + --hash=sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8 \ + --hash=sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887 \ + --hash=sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b \ + --hash=sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4 \ + --hash=sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f \ + --hash=sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5 \ + --hash=sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33 \ + --hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \ + --hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561 + # via requests +click==8.1.7 \ + --hash=sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28 \ + --hash=sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de + # via mkdocs +colorama==0.4.6 \ + --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ + --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 + # via mkdocs-material +ghp-import==2.1.0 \ + --hash=sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619 \ + --hash=sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343 + # via mkdocs +gitdb==4.0.11 \ + --hash=sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4 \ + --hash=sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b + # via gitpython +gitpython==3.1.41 \ + --hash=sha256:c36b6634d069b3f719610175020a9aed919421c87552185b085e04fbbdb10b7c \ + --hash=sha256:ed66e624884f76df22c8e16066d567aaa5a37d5b5fa19db2c6df6f7156db9048 + # via mkdocs-git-revision-date-plugin +idna==3.6 \ + --hash=sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca \ + --hash=sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f + # via requests +jinja2==3.1.3 \ + --hash=sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa \ + --hash=sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90 + # via + # mike + # mkdocs + # mkdocs-git-revision-date-plugin + # mkdocs-material +markdown==3.5.1 \ + --hash=sha256:5874b47d4ee3f0b14d764324d2c94c03ea66bee56f2d929da9f2508d65e722dc \ + --hash=sha256:b65d7beb248dc22f2e8a31fb706d93798093c308dc1aba295aedeb9d41a813bd + # via + # mkdocs + # mkdocs-material + # pymdown-extensions +markupsafe==2.1.3 \ + --hash=sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e \ + --hash=sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e \ + --hash=sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431 \ + --hash=sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686 \ + --hash=sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c \ + --hash=sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559 \ + --hash=sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc \ + --hash=sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb \ + --hash=sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939 \ + --hash=sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c \ + --hash=sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0 \ + --hash=sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4 \ + --hash=sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9 \ + --hash=sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575 \ + --hash=sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba \ + --hash=sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d \ + --hash=sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd \ + --hash=sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3 \ + --hash=sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00 \ + --hash=sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155 \ + --hash=sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac \ + --hash=sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52 \ + --hash=sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f \ + --hash=sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8 \ + --hash=sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b \ + --hash=sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007 \ + --hash=sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24 \ + --hash=sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea \ + --hash=sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198 \ + --hash=sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0 \ + --hash=sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee \ + --hash=sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be \ + --hash=sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2 \ + --hash=sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1 \ + --hash=sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707 \ + --hash=sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6 \ + --hash=sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c \ + --hash=sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58 \ + --hash=sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823 \ + --hash=sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779 \ + --hash=sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636 \ + --hash=sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c \ + --hash=sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad \ + --hash=sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee \ + --hash=sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc \ + --hash=sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2 \ + --hash=sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48 \ + --hash=sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7 \ + --hash=sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e \ + --hash=sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b \ + --hash=sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa \ + --hash=sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5 \ + --hash=sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e \ + --hash=sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb \ + --hash=sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9 \ + --hash=sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57 \ + --hash=sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc \ + --hash=sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc \ + --hash=sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2 \ + --hash=sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11 + # via + # jinja2 + # mkdocs +mergedeep==1.3.4 \ + --hash=sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8 \ + --hash=sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307 + # via mkdocs +mike==1.1.2 \ + --hash=sha256:4c307c28769834d78df10f834f57f810f04ca27d248f80a75f49c6fa2d1527ca \ + --hash=sha256:56c3f1794c2d0b5fdccfa9b9487beb013ca813de2e3ad0744724e9d34d40b77b + # via -r requirements.in +mkdocs==1.5.3 \ + --hash=sha256:3b3a78e736b31158d64dbb2f8ba29bd46a379d0c6e324c2246c3bc3d2189cfc1 \ + --hash=sha256:eb7c99214dcb945313ba30426c2451b735992c73c2e10838f76d09e39ff4d0e2 + # via + # mike + # mkdocs-exclude + # mkdocs-git-revision-date-plugin + # mkdocs-material +mkdocs-exclude==1.0.2 \ + --hash=sha256:ba6fab3c80ddbe3fd31d3e579861fd3124513708271180a5f81846da8c7e2a51 + # via -r requirements.in +mkdocs-git-revision-date-plugin==0.3.2 \ + --hash=sha256:2e67956cb01823dd2418e2833f3623dee8604cdf223bddd005fe36226a56f6ef + # via -r requirements.in +mkdocs-material==9.5.12 \ + --hash=sha256:5f69cef6a8aaa4050b812f72b1094fda3d079b9a51cf27a247244c03ec455e97 \ + --hash=sha256:d6f0c269f015e48c76291cdc79efb70f7b33bbbf42d649cfe475522ebee61b1f + # via -r requirements.in +mkdocs-material-extensions==1.3.1 \ + --hash=sha256:10c9511cea88f568257f960358a467d12b970e1f7b2c0e5fb2bb48cab1928443 \ + --hash=sha256:adff8b62700b25cb77b53358dad940f3ef973dd6db797907c49e3c2ef3ab4e31 + # via mkdocs-material +packaging==23.2 \ + --hash=sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5 \ + --hash=sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7 + # via mkdocs +paginate==0.5.6 \ + --hash=sha256:5e6007b6a9398177a7e1648d04fdd9f8c9766a1a945bceac82f1929e8c78af2d + # via mkdocs-material +pathspec==0.12.1 \ + --hash=sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08 \ + --hash=sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712 + # via mkdocs +platformdirs==4.1.0 \ + --hash=sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380 \ + --hash=sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420 + # via mkdocs +pygments==2.17.2 \ + --hash=sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c \ + --hash=sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367 + # via mkdocs-material +pymdown-extensions==10.5 \ + --hash=sha256:1b60f1e462adbec5a1ed79dac91f666c9c0d241fa294de1989f29d20096cfd0b \ + --hash=sha256:1f0ca8bb5beff091315f793ee17683bc1390731f6ac4c5eb01e27464b80fe879 + # via mkdocs-material +python-dateutil==2.8.2 \ + --hash=sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86 \ + --hash=sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9 + # via ghp-import +pyyaml==6.0.1 \ + --hash=sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5 \ + --hash=sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc \ + --hash=sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df \ + --hash=sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741 \ + --hash=sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206 \ + --hash=sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27 \ + --hash=sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595 \ + --hash=sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62 \ + --hash=sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98 \ + --hash=sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696 \ + --hash=sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290 \ + --hash=sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9 \ + --hash=sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d \ + --hash=sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6 \ + --hash=sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867 \ + --hash=sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47 \ + --hash=sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486 \ + --hash=sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6 \ + --hash=sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3 \ + --hash=sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007 \ + --hash=sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938 \ + --hash=sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0 \ + --hash=sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c \ + --hash=sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735 \ + --hash=sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d \ + --hash=sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28 \ + --hash=sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4 \ + --hash=sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba \ + --hash=sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8 \ + --hash=sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5 \ + --hash=sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd \ + --hash=sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3 \ + --hash=sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0 \ + --hash=sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515 \ + --hash=sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c \ + --hash=sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c \ + --hash=sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924 \ + --hash=sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34 \ + --hash=sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43 \ + --hash=sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859 \ + --hash=sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673 \ + --hash=sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54 \ + --hash=sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a \ + --hash=sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b \ + --hash=sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab \ + --hash=sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa \ + --hash=sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c \ + --hash=sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585 \ + --hash=sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d \ + --hash=sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f + # via + # mike + # mkdocs + # pymdown-extensions + # pyyaml-env-tag +pyyaml-env-tag==0.1 \ + --hash=sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb \ + --hash=sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069 + # via mkdocs +regex==2023.10.3 \ + --hash=sha256:00ba3c9818e33f1fa974693fb55d24cdc8ebafcb2e4207680669d8f8d7cca79a \ + --hash=sha256:00e871d83a45eee2f8688d7e6849609c2ca2a04a6d48fba3dff4deef35d14f07 \ + --hash=sha256:06e9abc0e4c9ab4779c74ad99c3fc10d3967d03114449acc2c2762ad4472b8ca \ + --hash=sha256:0b9ac09853b2a3e0d0082104036579809679e7715671cfbf89d83c1cb2a30f58 \ + --hash=sha256:0d47840dc05e0ba04fe2e26f15126de7c755496d5a8aae4a08bda4dd8d646c54 \ + --hash=sha256:0f649fa32fe734c4abdfd4edbb8381c74abf5f34bc0b3271ce687b23729299ed \ + --hash=sha256:107ac60d1bfdc3edb53be75e2a52aff7481b92817cfdddd9b4519ccf0e54a6ff \ + --hash=sha256:11175910f62b2b8c055f2b089e0fedd694fe2be3941b3e2633653bc51064c528 \ + --hash=sha256:12bd4bc2c632742c7ce20db48e0d99afdc05e03f0b4c1af90542e05b809a03d9 \ + --hash=sha256:16f8740eb6dbacc7113e3097b0a36065a02e37b47c936b551805d40340fb9971 \ + --hash=sha256:1c0e8fae5b27caa34177bdfa5a960c46ff2f78ee2d45c6db15ae3f64ecadde14 \ + --hash=sha256:2c54e23836650bdf2c18222c87f6f840d4943944146ca479858404fedeb9f9af \ + --hash=sha256:3367007ad1951fde612bf65b0dffc8fd681a4ab98ac86957d16491400d661302 \ + --hash=sha256:36362386b813fa6c9146da6149a001b7bd063dabc4d49522a1f7aa65b725c7ec \ + --hash=sha256:39807cbcbe406efca2a233884e169d056c35aa7e9f343d4e78665246a332f597 \ + --hash=sha256:39cdf8d141d6d44e8d5a12a8569d5a227f645c87df4f92179bd06e2e2705e76b \ + --hash=sha256:3b2c3502603fab52d7619b882c25a6850b766ebd1b18de3df23b2f939360e1bd \ + --hash=sha256:3ccf2716add72f80714b9a63899b67fa711b654be3fcdd34fa391d2d274ce767 \ + --hash=sha256:3fef4f844d2290ee0ba57addcec17eec9e3df73f10a2748485dfd6a3a188cc0f \ + --hash=sha256:4023e2efc35a30e66e938de5aef42b520c20e7eda7bb5fb12c35e5d09a4c43f6 \ + --hash=sha256:4a3ee019a9befe84fa3e917a2dd378807e423d013377a884c1970a3c2792d293 \ + --hash=sha256:4a8bf76e3182797c6b1afa5b822d1d5802ff30284abe4599e1247be4fd6b03be \ + --hash=sha256:4a992f702c9be9c72fa46f01ca6e18d131906a7180950958f766c2aa294d4b41 \ + --hash=sha256:4c34d4f73ea738223a094d8e0ffd6d2c1a1b4c175da34d6b0de3d8d69bee6bcc \ + --hash=sha256:4cd1bccf99d3ef1ab6ba835308ad85be040e6a11b0977ef7ea8c8005f01a3c29 \ + --hash=sha256:4ef80829117a8061f974b2fda8ec799717242353bff55f8a29411794d635d964 \ + --hash=sha256:58837f9d221744d4c92d2cf7201c6acd19623b50c643b56992cbd2b745485d3d \ + --hash=sha256:5a8f91c64f390ecee09ff793319f30a0f32492e99f5dc1c72bc361f23ccd0a9a \ + --hash=sha256:5addc9d0209a9afca5fc070f93b726bf7003bd63a427f65ef797a931782e7edc \ + --hash=sha256:6239d4e2e0b52c8bd38c51b760cd870069f0bdf99700a62cd509d7a031749a55 \ + --hash=sha256:66e2fe786ef28da2b28e222c89502b2af984858091675044d93cb50e6f46d7af \ + --hash=sha256:69c0771ca5653c7d4b65203cbfc5e66db9375f1078689459fe196fe08b7b4930 \ + --hash=sha256:6ac965a998e1388e6ff2e9781f499ad1eaa41e962a40d11c7823c9952c77123e \ + --hash=sha256:6c56c3d47da04f921b73ff9415fbaa939f684d47293f071aa9cbb13c94afc17d \ + --hash=sha256:6f85739e80d13644b981a88f529d79c5bdf646b460ba190bffcaf6d57b2a9863 \ + --hash=sha256:706e7b739fdd17cb89e1fbf712d9dc21311fc2333f6d435eac2d4ee81985098c \ + --hash=sha256:741ba2f511cc9626b7561a440f87d658aabb3d6b744a86a3c025f866b4d19e7f \ + --hash=sha256:7434a61b158be563c1362d9071358f8ab91b8d928728cd2882af060481244c9e \ + --hash=sha256:76066d7ff61ba6bf3cb5efe2428fc82aac91802844c022d849a1f0f53820502d \ + --hash=sha256:7979b834ec7a33aafae34a90aad9f914c41fd6eaa8474e66953f3f6f7cbd4368 \ + --hash=sha256:7eece6fbd3eae4a92d7c748ae825cbc1ee41a89bb1c3db05b5578ed3cfcfd7cb \ + --hash=sha256:7ef1e014eed78ab650bef9a6a9cbe50b052c0aebe553fb2881e0453717573f52 \ + --hash=sha256:81dce2ddc9f6e8f543d94b05d56e70d03a0774d32f6cca53e978dc01e4fc75b8 \ + --hash=sha256:82fcc1f1cc3ff1ab8a57ba619b149b907072e750815c5ba63e7aa2e1163384a4 \ + --hash=sha256:8d1f21af4c1539051049796a0f50aa342f9a27cde57318f2fc41ed50b0dbc4ac \ + --hash=sha256:90a79bce019c442604662d17bf69df99090e24cdc6ad95b18b6725c2988a490e \ + --hash=sha256:9145f092b5d1977ec8c0ab46e7b3381b2fd069957b9862a43bd383e5c01d18c2 \ + --hash=sha256:91dc1d531f80c862441d7b66c4505cd6ea9d312f01fb2f4654f40c6fdf5cc37a \ + --hash=sha256:979c24cbefaf2420c4e377ecd1f165ea08cc3d1fbb44bdc51bccbbf7c66a2cb4 \ + --hash=sha256:994645a46c6a740ee8ce8df7911d4aee458d9b1bc5639bc968226763d07f00fa \ + --hash=sha256:9b98b7681a9437262947f41c7fac567c7e1f6eddd94b0483596d320092004533 \ + --hash=sha256:9c6b4d23c04831e3ab61717a707a5d763b300213db49ca680edf8bf13ab5d91b \ + --hash=sha256:9c6d0ced3c06d0f183b73d3c5920727268d2201aa0fe6d55c60d68c792ff3588 \ + --hash=sha256:9fd88f373cb71e6b59b7fa597e47e518282455c2734fd4306a05ca219a1991b0 \ + --hash=sha256:a8f4e49fc3ce020f65411432183e6775f24e02dff617281094ba6ab079ef0915 \ + --hash=sha256:a9e908ef5889cda4de038892b9accc36d33d72fb3e12c747e2799a0e806ec841 \ + --hash=sha256:ad08a69728ff3c79866d729b095872afe1e0557251da4abb2c5faff15a91d19a \ + --hash=sha256:adbccd17dcaff65704c856bd29951c58a1bd4b2b0f8ad6b826dbd543fe740988 \ + --hash=sha256:b0c7d2f698e83f15228ba41c135501cfe7d5740181d5903e250e47f617eb4292 \ + --hash=sha256:b3ab05a182c7937fb374f7e946f04fb23a0c0699c0450e9fb02ef567412d2fa3 \ + --hash=sha256:b6104f9a46bd8743e4f738afef69b153c4b8b592d35ae46db07fc28ae3d5fb7c \ + --hash=sha256:ba7cd6dc4d585ea544c1412019921570ebd8a597fabf475acc4528210d7c4a6f \ + --hash=sha256:bc72c231f5449d86d6c7d9cc7cd819b6eb30134bb770b8cfdc0765e48ef9c420 \ + --hash=sha256:bce8814b076f0ce5766dc87d5a056b0e9437b8e0cd351b9a6c4e1134a7dfbda9 \ + --hash=sha256:be5e22bbb67924dea15039c3282fa4cc6cdfbe0cbbd1c0515f9223186fc2ec5f \ + --hash=sha256:be6b7b8d42d3090b6c80793524fa66c57ad7ee3fe9722b258aec6d0672543fd0 \ + --hash=sha256:bfe50b61bab1b1ec260fa7cd91106fa9fece57e6beba05630afe27c71259c59b \ + --hash=sha256:bff507ae210371d4b1fe316d03433ac099f184d570a1a611e541923f78f05037 \ + --hash=sha256:c148bec483cc4b421562b4bcedb8e28a3b84fcc8f0aa4418e10898f3c2c0eb9b \ + --hash=sha256:c15ad0aee158a15e17e0495e1e18741573d04eb6da06d8b84af726cfc1ed02ee \ + --hash=sha256:c2169b2dcabf4e608416f7f9468737583ce5f0a6e8677c4efbf795ce81109d7c \ + --hash=sha256:c55853684fe08d4897c37dfc5faeff70607a5f1806c8be148f1695be4a63414b \ + --hash=sha256:c65a3b5330b54103e7d21cac3f6bf3900d46f6d50138d73343d9e5b2900b2353 \ + --hash=sha256:c7964c2183c3e6cce3f497e3a9f49d182e969f2dc3aeeadfa18945ff7bdd7051 \ + --hash=sha256:cc3f1c053b73f20c7ad88b0d1d23be7e7b3901229ce89f5000a8399746a6e039 \ + --hash=sha256:ce615c92d90df8373d9e13acddd154152645c0dc060871abf6bd43809673d20a \ + --hash=sha256:d29338556a59423d9ff7b6eb0cb89ead2b0875e08fe522f3e068b955c3e7b59b \ + --hash=sha256:d8a993c0a0ffd5f2d3bda23d0cd75e7086736f8f8268de8a82fbc4bd0ac6791e \ + --hash=sha256:d9c727bbcf0065cbb20f39d2b4f932f8fa1631c3e01fcedc979bd4f51fe051c5 \ + --hash=sha256:dac37cf08fcf2094159922edc7a2784cfcc5c70f8354469f79ed085f0328ebdf \ + --hash=sha256:dd829712de97753367153ed84f2de752b86cd1f7a88b55a3a775eb52eafe8a94 \ + --hash=sha256:e54ddd0bb8fb626aa1f9ba7b36629564544954fff9669b15da3610c22b9a0991 \ + --hash=sha256:e77c90ab5997e85901da85131fd36acd0ed2221368199b65f0d11bca44549711 \ + --hash=sha256:ebedc192abbc7fd13c5ee800e83a6df252bec691eb2c4bedc9f8b2e2903f5e2a \ + --hash=sha256:ef71561f82a89af6cfcbee47f0fabfdb6e63788a9258e913955d89fdd96902ab \ + --hash=sha256:f0a47efb1dbef13af9c9a54a94a0b814902e547b7f21acb29434504d18f36e3a \ + --hash=sha256:f4f2ca6df64cbdd27f27b34f35adb640b5d2d77264228554e68deda54456eb11 \ + --hash=sha256:fb02e4257376ae25c6dd95a5aec377f9b18c09be6ebdefa7ad209b9137b73d48 + # via mkdocs-material +requests==2.31.0 \ + --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \ + --hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1 + # via mkdocs-material +six==1.16.0 \ + --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ + --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 + # via python-dateutil +smmap==5.0.1 \ + --hash=sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62 \ + --hash=sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da + # via gitdb +urllib3==2.1.0 \ + --hash=sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3 \ + --hash=sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54 + # via requests +verspec==0.1.0 \ + --hash=sha256:741877d5633cc9464c45a469ae2a31e801e6dbbaa85b9675d481cda100f11c31 \ + --hash=sha256:c4504ca697b2056cdb4bfa7121461f5a0e81809255b41c03dda4ba823637c01e + # via mike +watchdog==3.0.0 \ + --hash=sha256:0e06ab8858a76e1219e68c7573dfeba9dd1c0219476c5a44d5333b01d7e1743a \ + --hash=sha256:13bbbb462ee42ec3c5723e1205be8ced776f05b100e4737518c67c8325cf6100 \ + --hash=sha256:233b5817932685d39a7896b1090353fc8efc1ef99c9c054e46c8002561252fb8 \ + --hash=sha256:25f70b4aa53bd743729c7475d7ec41093a580528b100e9a8c5b5efe8899592fc \ + --hash=sha256:2b57a1e730af3156d13b7fdddfc23dea6487fceca29fc75c5a868beed29177ae \ + --hash=sha256:336adfc6f5cc4e037d52db31194f7581ff744b67382eb6021c868322e32eef41 \ + --hash=sha256:3aa7f6a12e831ddfe78cdd4f8996af9cf334fd6346531b16cec61c3b3c0d8da0 \ + --hash=sha256:3ed7c71a9dccfe838c2f0b6314ed0d9b22e77d268c67e015450a29036a81f60f \ + --hash=sha256:4c9956d27be0bb08fc5f30d9d0179a855436e655f046d288e2bcc11adfae893c \ + --hash=sha256:4d98a320595da7a7c5a18fc48cb633c2e73cda78f93cac2ef42d42bf609a33f9 \ + --hash=sha256:4f94069eb16657d2c6faada4624c39464f65c05606af50bb7902e036e3219be3 \ + --hash=sha256:5113334cf8cf0ac8cd45e1f8309a603291b614191c9add34d33075727a967709 \ + --hash=sha256:51f90f73b4697bac9c9a78394c3acbbd331ccd3655c11be1a15ae6fe289a8c83 \ + --hash=sha256:5d9f3a10e02d7371cd929b5d8f11e87d4bad890212ed3901f9b4d68767bee759 \ + --hash=sha256:7ade88d0d778b1b222adebcc0927428f883db07017618a5e684fd03b83342bd9 \ + --hash=sha256:7c5f84b5194c24dd573fa6472685b2a27cc5a17fe5f7b6fd40345378ca6812e3 \ + --hash=sha256:7e447d172af52ad204d19982739aa2346245cc5ba6f579d16dac4bfec226d2e7 \ + --hash=sha256:8ae9cda41fa114e28faf86cb137d751a17ffd0316d1c34ccf2235e8a84365c7f \ + --hash=sha256:8f3ceecd20d71067c7fd4c9e832d4e22584318983cabc013dbf3f70ea95de346 \ + --hash=sha256:9fac43a7466eb73e64a9940ac9ed6369baa39b3bf221ae23493a9ec4d0022674 \ + --hash=sha256:a70a8dcde91be523c35b2bf96196edc5730edb347e374c7de7cd20c43ed95397 \ + --hash=sha256:adfdeab2da79ea2f76f87eb42a3ab1966a5313e5a69a0213a3cc06ef692b0e96 \ + --hash=sha256:ba07e92756c97e3aca0912b5cbc4e5ad802f4557212788e72a72a47ff376950d \ + --hash=sha256:c07253088265c363d1ddf4b3cdb808d59a0468ecd017770ed716991620b8f77a \ + --hash=sha256:c9d8c8ec7efb887333cf71e328e39cffbf771d8f8f95d308ea4125bf5f90ba64 \ + --hash=sha256:d00e6be486affb5781468457b21a6cbe848c33ef43f9ea4a73b4882e5f188a44 \ + --hash=sha256:d429c2430c93b7903914e4db9a966c7f2b068dd2ebdd2fa9b9ce094c7d459f33 + # via mkdocs diff --git a/docs/roadmap.md b/docs/roadmap.md index 1774b5323f..05942052ca 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -44,7 +44,7 @@ Just like for the feature parity, if you have any feedback or would like to cont ### Improve operational excellence -We continue to work on increasing operational excellence to remove as much undifferentiated heavylifting for maintainers, so that we can focus on delivering features that help you. +We continue to work on increasing operational excellence to remove as much undifferentiated heavy lifting for maintainers, so that we can focus on delivering features that help you. This means improving our automation workflows, project management, and test coverage. diff --git a/docs/snippets/CHANGELOG.md b/docs/snippets/CHANGELOG.md new file mode 100644 index 0000000000..01339b5224 --- /dev/null +++ b/docs/snippets/CHANGELOG.md @@ -0,0 +1,24 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +## 2.0.2 (2024-03-05) + +**Note:** Version bump only for package docs + + + + + +## 2.0.1 (2024-03-04) + +**Note:** Version bump only for package docs + + + + + +# [2.0.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.18.1...v2.0.0) (2024-03-04) + +**Note:** Version bump only for package docs diff --git a/docs/snippets/batch/advancedTracingRecordHandler.ts b/docs/snippets/batch/advancedTracingRecordHandler.ts index a65c9f976d..ea85b6833a 100644 --- a/docs/snippets/batch/advancedTracingRecordHandler.ts +++ b/docs/snippets/batch/advancedTracingRecordHandler.ts @@ -3,7 +3,8 @@ import { EventType, processPartialResponse, } from '@aws-lambda-powertools/batch'; -import { Tracer, captureLambdaHandler } from '@aws-lambda-powertools/tracer'; +import { Tracer } from '@aws-lambda-powertools/tracer'; +import { captureLambdaHandler } from '@aws-lambda-powertools/tracer/middleware'; import middy from '@middy/core'; import type { SQSEvent, diff --git a/docs/snippets/batch/customPartialProcessor.ts b/docs/snippets/batch/customPartialProcessor.ts index e634b74d53..65bcd1694c 100644 --- a/docs/snippets/batch/customPartialProcessor.ts +++ b/docs/snippets/batch/customPartialProcessor.ts @@ -13,7 +13,7 @@ import type { SuccessResponse, FailureResponse, BaseRecord, -} from '@aws-lambda-powertools/batch'; +} from '@aws-lambda-powertools/batch/types'; import type { SQSEvent, Context, SQSBatchResponse } from 'aws-lambda'; const tableName = process.env.TABLE_NAME || 'table-not-found'; diff --git a/docs/snippets/batch/extendingFailure.ts b/docs/snippets/batch/extendingFailure.ts index ab1ef530f9..ccfa78966a 100644 --- a/docs/snippets/batch/extendingFailure.ts +++ b/docs/snippets/batch/extendingFailure.ts @@ -1,11 +1,13 @@ -import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; +import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics'; import { BatchProcessor, EventType, - FailureResponse, - EventSourceType, processPartialResponse, } from '@aws-lambda-powertools/batch'; +import type { + FailureResponse, + EventSourceDataClassTypes, +} from '@aws-lambda-powertools/batch/types'; import { Logger } from '@aws-lambda-powertools/logger'; import type { SQSEvent, @@ -23,10 +25,10 @@ class MyProcessor extends BatchProcessor { } public failureHandler( - record: EventSourceType, + record: EventSourceDataClassTypes, error: Error ): FailureResponse { - this.#metrics.addMetric('BatchRecordFailures', MetricUnits.Count, 1); + this.#metrics.addMetric('BatchRecordFailures', MetricUnit.Count, 1); return super.failureHandler(record, error); } diff --git a/docs/snippets/batch/gettingStartedErrorHandling.ts b/docs/snippets/batch/gettingStartedErrorHandling.ts index 20b2b32f60..3f36c18e62 100644 --- a/docs/snippets/batch/gettingStartedErrorHandling.ts +++ b/docs/snippets/batch/gettingStartedErrorHandling.ts @@ -28,7 +28,7 @@ const recordHandler = async (record: SQSRecord): Promise => { logger.info('Processed item', { item }); } else { // prettier-ignore - throw new InvalidPayload('Payload does not contain minumum required fields'); // (1)! + throw new InvalidPayload('Payload does not contain minimum required fields'); // (1)! } }; diff --git a/docs/snippets/batch/templates/sam/dynamodb.yaml b/docs/snippets/batch/templates/sam/dynamodb.yaml index c95dea07b7..83dc648054 100644 --- a/docs/snippets/batch/templates/sam/dynamodb.yaml +++ b/docs/snippets/batch/templates/sam/dynamodb.yaml @@ -6,11 +6,11 @@ Globals: Function: Timeout: 5 MemorySize: 256 - Runtime: nodejs18.x + Runtime: nodejs20.x Tracing: Active Environment: Variables: - LOG_LEVEL: INFO + POWERTOOLS_LOG_LEVEL: INFO POWERTOOLS_SERVICE_NAME: hello Resources: diff --git a/docs/snippets/batch/templates/sam/kinesis.yaml b/docs/snippets/batch/templates/sam/kinesis.yaml index 032b354a74..3de5232790 100644 --- a/docs/snippets/batch/templates/sam/kinesis.yaml +++ b/docs/snippets/batch/templates/sam/kinesis.yaml @@ -6,7 +6,7 @@ Globals: Function: Timeout: 5 MemorySize: 256 - Runtime: nodejs18.x + Runtime: nodejs20.x Tracing: Active Environment: Variables: diff --git a/docs/snippets/batch/templates/sam/sqs.yaml b/docs/snippets/batch/templates/sam/sqs.yaml index 65b91507eb..77ce058c94 100644 --- a/docs/snippets/batch/templates/sam/sqs.yaml +++ b/docs/snippets/batch/templates/sam/sqs.yaml @@ -6,11 +6,11 @@ Globals: Function: Timeout: 5 MemorySize: 256 - Runtime: nodejs18.x + Runtime: nodejs20.x Tracing: Active Environment: Variables: - LOG_LEVEL: INFO + POWERTOOLS_LOG_LEVEL: INFO POWERTOOLS_SERVICE_NAME: hello Resources: diff --git a/docs/snippets/batch/testingYourCode.ts b/docs/snippets/batch/testingYourCode.ts index a7ffa0e5be..d477e3dfc6 100644 --- a/docs/snippets/batch/testingYourCode.ts +++ b/docs/snippets/batch/testingYourCode.ts @@ -1,7 +1,22 @@ -import { ContextExamples as dummyContext } from '@aws-lambda-powertools/commons'; import { handler, processor } from './gettingStartedSQS'; import sqsEvent from './samples/sampleSQSEvent.json'; +const context = { + callbackWaitsForEmptyEventLoop: true, + functionVersion: '$LATEST', + functionName: 'foo-bar-function', + memoryLimitInMB: '128', + logGroupName: '/aws/lambda/foo-bar-function-123456abcdef', + logStreamName: '2021/03/09/[$LATEST]abcdef123456abcdef123456abcdef123456', + invokedFunctionArn: + 'arn:aws:lambda:eu-west-1:123456789012:function:foo-bar-function', + awsRequestId: 'c6af9ac6-7b61-11e6-9a41-93e812345678', + getRemainingTimeInMillis: () => 1234, + done: () => console.log('Done!'), + fail: () => console.log('Failed!'), + succeed: () => console.log('Succeeded!'), +}; + describe('Function tests', () => { beforeEach(() => { jest.clearAllMocks(); @@ -9,7 +24,6 @@ describe('Function tests', () => { test('should return one failed message', async () => { // Prepare - const context = dummyContext.helloworldContext; const processorResult = processor; // access processor for additional assertions const successfulRecord = sqsEvent.Records[0]; const failedRecord = sqsEvent.Records[1]; diff --git a/docs/snippets/idempotency/idempotentDecoratorBase.ts b/docs/snippets/idempotency/idempotentDecoratorBase.ts index 852ddae075..409a34647f 100644 --- a/docs/snippets/idempotency/idempotentDecoratorBase.ts +++ b/docs/snippets/idempotency/idempotentDecoratorBase.ts @@ -1,5 +1,5 @@ import type { Context } from 'aws-lambda'; -import type { LambdaInterface } from '@aws-lambda-powertools/commons'; +import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; import { IdempotencyConfig, idempotent, diff --git a/docs/snippets/idempotency/templates/tableCdk.ts b/docs/snippets/idempotency/templates/tableCdk.ts index 8a07d5dc3c..526ce48156 100644 --- a/docs/snippets/idempotency/templates/tableCdk.ts +++ b/docs/snippets/idempotency/templates/tableCdk.ts @@ -18,7 +18,7 @@ export class IdempotencyStack extends Stack { }); const fnHandler = new NodejsFunction(this, 'helloWorldFunction', { - runtime: Runtime.NODEJS_18_X, + runtime: Runtime.NODEJS_20_X, handler: 'handler', entry: 'src/index.ts', environment: { diff --git a/docs/snippets/idempotency/templates/tableSam.yaml b/docs/snippets/idempotency/templates/tableSam.yaml index 010ecc89ca..ccd2078aee 100644 --- a/docs/snippets/idempotency/templates/tableSam.yaml +++ b/docs/snippets/idempotency/templates/tableSam.yaml @@ -17,7 +17,7 @@ Resources: HelloWorldFunction: Type: AWS::Serverless::Function Properties: - Runtime: python3.11 + Runtime: nodejs20.x Handler: app.py Policies: - Statement: diff --git a/docs/snippets/idempotency/templates/tableTerraform.tf b/docs/snippets/idempotency/templates/tableTerraform.tf index 4856f2b0e6..bedd2f6b5e 100644 --- a/docs/snippets/idempotency/templates/tableTerraform.tf +++ b/docs/snippets/idempotency/templates/tableTerraform.tf @@ -28,7 +28,7 @@ resource "aws_dynamodb_table" "IdempotencyTable" { resource "aws_lambda_function" "IdempotencyFunction" { function_name = "IdempotencyFunction" role = aws_iam_role.IdempotencyFunctionRole.arn - runtime = "nodejs18.x" + runtime = "nodejs20.x" handler = "index.handler" filename = "lambda.zip" } diff --git a/docs/snippets/logger/bringYourOwnFormatterClass.ts b/docs/snippets/logger/bringYourOwnFormatterClass.ts index 9d189b2b8b..48c5642d8c 100644 --- a/docs/snippets/logger/bringYourOwnFormatterClass.ts +++ b/docs/snippets/logger/bringYourOwnFormatterClass.ts @@ -1,9 +1,8 @@ -import { LogFormatter } from '@aws-lambda-powertools/logger'; -import { +import { LogFormatter, LogItem } from '@aws-lambda-powertools/logger'; +import type { LogAttributes, UnformattedAttributes, -} from '@aws-lambda-powertools/logger/lib/types'; -import { LogItem } from '@aws-lambda-powertools/logger/lib/log'; +} from '@aws-lambda-powertools/logger/types'; // Replace this line with your own type type MyCompanyLog = LogAttributes; diff --git a/docs/snippets/logger/bringYourOwnFormatterHandler.ts b/docs/snippets/logger/bringYourOwnFormatterHandler.ts index c374c4a255..7eadd526c0 100644 --- a/docs/snippets/logger/bringYourOwnFormatterHandler.ts +++ b/docs/snippets/logger/bringYourOwnFormatterHandler.ts @@ -1,5 +1,6 @@ import { Logger } from '@aws-lambda-powertools/logger'; -import { MyCompanyLogFormatter } from './utils/formatters/MyCompanyLogFormatter'; +import { MyCompanyLogFormatter } from './bringYourOwnFormatterClass'; +import type { Context } from 'aws-lambda'; const logger = new Logger({ logFormatter: new MyCompanyLogFormatter(), @@ -15,7 +16,10 @@ const logger = new Logger({ }, }); -export const handler = async (event, context): Promise => { +export const handler = async ( + _event: unknown, + context: Context +): Promise => { logger.addContext(context); logger.info('This is an INFO log', { diff --git a/docs/snippets/logger/clearStateDecorator.ts b/docs/snippets/logger/clearStateDecorator.ts index e31d66b190..0f4ec2b81f 100644 --- a/docs/snippets/logger/clearStateDecorator.ts +++ b/docs/snippets/logger/clearStateDecorator.ts @@ -1,5 +1,5 @@ import { Logger } from '@aws-lambda-powertools/logger'; -import { LambdaInterface } from '@aws-lambda-powertools/commons'; +import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; // Persistent attributes added outside the handler will be // cached across invocations @@ -14,12 +14,15 @@ const logger = new Logger({ class Lambda implements LambdaInterface { // Enable the clear state flag @logger.injectLambdaContext({ clearState: true }) - public async handler(event: unknown, _context: unknown): Promise { + public async handler( + event: { specialKey: string }, + _context: unknown + ): Promise { // Persistent attributes added inside the handler will NOT be cached // across invocations - if (event['special_key'] === '123456') { + if (event['specialKey'] === '123456') { logger.appendKeys({ - details: { special_key: '123456' }, + details: { specialKey: '123456' }, }); } logger.debug('This is a DEBUG log'); diff --git a/docs/snippets/logger/clearStateMiddy.ts b/docs/snippets/logger/clearStateMiddy.ts index 7696c75b63..1c18e550a0 100644 --- a/docs/snippets/logger/clearStateMiddy.ts +++ b/docs/snippets/logger/clearStateMiddy.ts @@ -1,4 +1,5 @@ -import { Logger, injectLambdaContext } from '@aws-lambda-powertools/logger'; +import { Logger } from '@aws-lambda-powertools/logger'; +import { injectLambdaContext } from '@aws-lambda-powertools/logger/middleware'; import middy from '@middy/core'; // Persistent attributes added outside the handler will be @@ -12,14 +13,14 @@ const logger = new Logger({ }); const lambdaHandler = async ( - event: { special_key: string }, + event: { specialKey: string }, _context: unknown ): Promise => { // Persistent attributes added inside the handler will NOT be cached // across invocations if (event['special_key'] === '123456') { logger.appendKeys({ - details: { special_key: event['special_key'] }, + details: { special_key: event['specialKey'] }, }); } logger.debug('This is a DEBUG log'); diff --git a/docs/snippets/logger/decorator.ts b/docs/snippets/logger/decorator.ts index 0cd9be0cf4..1f3317596a 100644 --- a/docs/snippets/logger/decorator.ts +++ b/docs/snippets/logger/decorator.ts @@ -1,5 +1,5 @@ import { Logger } from '@aws-lambda-powertools/logger'; -import { LambdaInterface } from '@aws-lambda-powertools/commons'; +import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; const logger = new Logger(); diff --git a/docs/snippets/logger/eventDecorator.ts b/docs/snippets/logger/eventDecorator.ts index 9adf1518f1..bded346d2b 100644 --- a/docs/snippets/logger/eventDecorator.ts +++ b/docs/snippets/logger/eventDecorator.ts @@ -1,5 +1,5 @@ import { Logger } from '@aws-lambda-powertools/logger'; -import { LambdaInterface } from '@aws-lambda-powertools/commons'; +import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; const logger = new Logger(); diff --git a/docs/snippets/logger/eventMiddy.ts b/docs/snippets/logger/eventMiddy.ts index a3648c734a..3c3a40596b 100644 --- a/docs/snippets/logger/eventMiddy.ts +++ b/docs/snippets/logger/eventMiddy.ts @@ -1,4 +1,5 @@ -import { Logger, injectLambdaContext } from '@aws-lambda-powertools/logger'; +import { Logger } from '@aws-lambda-powertools/logger'; +import { injectLambdaContext } from '@aws-lambda-powertools/logger/middleware'; import middy from '@middy/core'; const logger = new Logger(); diff --git a/docs/snippets/logger/manual.ts b/docs/snippets/logger/manual.ts index 00eaa38ac5..287b5beea0 100644 --- a/docs/snippets/logger/manual.ts +++ b/docs/snippets/logger/manual.ts @@ -1,8 +1,12 @@ import { Logger } from '@aws-lambda-powertools/logger'; +import type { Context } from 'aws-lambda'; const logger = new Logger(); -export const handler = async (_event, context): Promise => { +export const handler = async ( + _event: unknown, + context: Context +): Promise => { logger.addContext(context); logger.info('This is an INFO log with some context'); diff --git a/docs/snippets/logger/middy.ts b/docs/snippets/logger/middy.ts index f0dcbaa5aa..d92320abfe 100644 --- a/docs/snippets/logger/middy.ts +++ b/docs/snippets/logger/middy.ts @@ -1,4 +1,5 @@ -import { Logger, injectLambdaContext } from '@aws-lambda-powertools/logger'; +import { Logger } from '@aws-lambda-powertools/logger'; +import { injectLambdaContext } from '@aws-lambda-powertools/logger/middleware'; import middy from '@middy/core'; const logger = new Logger(); diff --git a/docs/snippets/logger/unitTesting.ts b/docs/snippets/logger/unitTesting.ts index d120be2858..671c93c181 100644 --- a/docs/snippets/logger/unitTesting.ts +++ b/docs/snippets/logger/unitTesting.ts @@ -1,8 +1,24 @@ -import { ContextExamples as dummyContext } from '@aws-lambda-powertools/commons'; +declare const handler: (event: unknown, context: unknown) => Promise; + +const context = { + callbackWaitsForEmptyEventLoop: true, + functionVersion: '$LATEST', + functionName: 'foo-bar-function', + memoryLimitInMB: '128', + logGroupName: '/aws/lambda/foo-bar-function-123456abcdef', + logStreamName: '2021/03/09/[$LATEST]abcdef123456abcdef123456abcdef123456', + invokedFunctionArn: + 'arn:aws:lambda:eu-west-1:123456789012:function:foo-bar-function', + awsRequestId: 'c6af9ac6-7b61-11e6-9a41-93e812345678', + getRemainingTimeInMillis: () => 1234, + done: () => console.log('Done!'), + fail: () => console.log('Failed!'), + succeed: () => console.log('Succeeded!'), +}; describe('MyUnitTest', () => { test('Lambda invoked successfully', async () => { const testEvent = { test: 'test' }; - await handler(testEvent, dummyContext); + await handler(testEvent, context); }); }); diff --git a/docs/snippets/metrics/addHighResolutionMetric.ts b/docs/snippets/metrics/addHighResolutionMetric.ts index f2981b8514..001f753278 100644 --- a/docs/snippets/metrics/addHighResolutionMetric.ts +++ b/docs/snippets/metrics/addHighResolutionMetric.ts @@ -1,6 +1,6 @@ import { Metrics, - MetricUnits, + MetricUnit, MetricResolution, } from '@aws-lambda-powertools/metrics'; @@ -15,7 +15,7 @@ export const handler = async ( ): Promise => { metrics.addMetric( 'successfulBooking', - MetricUnits.Count, + MetricUnit.Count, 1, MetricResolution.High ); diff --git a/docs/snippets/metrics/addMetadata.ts b/docs/snippets/metrics/addMetadata.ts index 6836191b91..9e86310e67 100644 --- a/docs/snippets/metrics/addMetadata.ts +++ b/docs/snippets/metrics/addMetadata.ts @@ -1,8 +1,5 @@ -import { - Metrics, - MetricUnits, - logMetrics, -} from '@aws-lambda-powertools/metrics'; +import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics'; +import { logMetrics } from '@aws-lambda-powertools/metrics/middleware'; import middy from '@middy/core'; const metrics = new Metrics({ @@ -14,7 +11,7 @@ const lambdaHandler = async ( _event: unknown, _context: unknown ): Promise => { - metrics.addMetric('successfulBooking', MetricUnits.Count, 1); + metrics.addMetric('successfulBooking', MetricUnit.Count, 1); metrics.addMetadata('bookingId', '7051cd10-6283-11ec-90d6-0242ac120003'); }; diff --git a/docs/snippets/metrics/basicUsage.ts b/docs/snippets/metrics/basicUsage.ts index 868f5b67af..1deb2285bb 100644 --- a/docs/snippets/metrics/basicUsage.ts +++ b/docs/snippets/metrics/basicUsage.ts @@ -1,4 +1,4 @@ -import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; +import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics'; const metrics = new Metrics({ namespace: 'serverlessAirline', @@ -9,5 +9,5 @@ export const handler = async ( _event: unknown, _context: unknown ): Promise => { - metrics.addMetric('successfulBooking', MetricUnits.Count, 1); + metrics.addMetric('successfulBooking', MetricUnit.Count, 1); }; diff --git a/docs/snippets/metrics/captureColdStartMetricDecorator.ts b/docs/snippets/metrics/captureColdStartMetricDecorator.ts index d2e050224e..390657c93f 100644 --- a/docs/snippets/metrics/captureColdStartMetricDecorator.ts +++ b/docs/snippets/metrics/captureColdStartMetricDecorator.ts @@ -1,5 +1,5 @@ -import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; -import { LambdaInterface } from '@aws-lambda-powertools/commons'; +import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics'; +import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; const metrics = new Metrics({ namespace: 'serverlessAirline', @@ -9,6 +9,6 @@ const metrics = new Metrics({ export class MyFunction implements LambdaInterface { @metrics.logMetrics({ captureColdStartMetric: true }) public async handler(_event: unknown, _context: unknown): Promise { - metrics.addMetric('successfulBooking', MetricUnits.Count, 1); + metrics.addMetric('successfulBooking', MetricUnit.Count, 1); } } diff --git a/docs/snippets/metrics/captureColdStartMetricMiddy.ts b/docs/snippets/metrics/captureColdStartMetricMiddy.ts index c598a09e03..a09ada1939 100644 --- a/docs/snippets/metrics/captureColdStartMetricMiddy.ts +++ b/docs/snippets/metrics/captureColdStartMetricMiddy.ts @@ -1,8 +1,5 @@ -import { - Metrics, - MetricUnits, - logMetrics, -} from '@aws-lambda-powertools/metrics'; +import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics'; +import { logMetrics } from '@aws-lambda-powertools/metrics/middleware'; import middy from '@middy/core'; const metrics = new Metrics({ @@ -14,7 +11,7 @@ const lambdaHandler = async ( _event: unknown, _context: unknown ): Promise => { - metrics.addMetric('successfulBooking', MetricUnits.Count, 1); + metrics.addMetric('successfulBooking', MetricUnit.Count, 1); }; export const handler = middy(lambdaHandler).use( diff --git a/docs/snippets/metrics/createMetrics.ts b/docs/snippets/metrics/createMetrics.ts index e7065e8f29..9a66a1bbb3 100644 --- a/docs/snippets/metrics/createMetrics.ts +++ b/docs/snippets/metrics/createMetrics.ts @@ -1,4 +1,4 @@ -import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; +import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics'; const metrics = new Metrics({ namespace: 'serverlessAirline', @@ -9,6 +9,6 @@ export const handler = async ( _event: unknown, _context: unknown ): Promise => { - metrics.addMetric('successfulBooking', MetricUnits.Count, 1); + metrics.addMetric('successfulBooking', MetricUnit.Count, 1); metrics.publishStoredMetrics(); }; diff --git a/docs/snippets/metrics/customDimensions.ts b/docs/snippets/metrics/customDimensions.ts index 8eeaebebda..a36473571c 100644 --- a/docs/snippets/metrics/customDimensions.ts +++ b/docs/snippets/metrics/customDimensions.ts @@ -1,4 +1,4 @@ -import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; +import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics'; const metrics = new Metrics({ namespace: 'serverlessAirline', @@ -10,6 +10,6 @@ export const handler = async ( _context: unknown ): Promise => { metrics.addDimension('environment', 'prod'); - metrics.addMetric('successfulBooking', MetricUnits.Count, 1); + metrics.addMetric('successfulBooking', MetricUnit.Count, 1); metrics.publishStoredMetrics(); }; diff --git a/docs/snippets/metrics/decorator.ts b/docs/snippets/metrics/decorator.ts index 9d69c5fa56..3595cc41d2 100644 --- a/docs/snippets/metrics/decorator.ts +++ b/docs/snippets/metrics/decorator.ts @@ -1,5 +1,5 @@ -import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; -import { LambdaInterface } from '@aws-lambda-powertools/commons'; +import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics'; +import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; const metrics = new Metrics({ namespace: 'serverlessAirline', @@ -9,7 +9,7 @@ const metrics = new Metrics({ class Lambda implements LambdaInterface { @metrics.logMetrics() public async handler(_event: unknown, _context: unknown): Promise { - metrics.addMetric('successfulBooking', MetricUnits.Count, 1); + metrics.addMetric('successfulBooking', MetricUnit.Count, 1); } } diff --git a/docs/snippets/metrics/defaultDimensions.ts b/docs/snippets/metrics/defaultDimensions.ts index c0bc92b99b..7c0340e5f5 100644 --- a/docs/snippets/metrics/defaultDimensions.ts +++ b/docs/snippets/metrics/defaultDimensions.ts @@ -1,4 +1,4 @@ -import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; +import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics'; const metrics = new Metrics({ namespace: 'serverlessAirline', @@ -10,5 +10,5 @@ export const handler = async ( _event: unknown, _context: unknown ): Promise => { - metrics.addMetric('successfulBooking', MetricUnits.Count, 1); + metrics.addMetric('successfulBooking', MetricUnit.Count, 1); }; diff --git a/docs/snippets/metrics/defaultDimensionsDecorator.ts b/docs/snippets/metrics/defaultDimensionsDecorator.ts index 23796a16fc..3c3767ecfd 100644 --- a/docs/snippets/metrics/defaultDimensionsDecorator.ts +++ b/docs/snippets/metrics/defaultDimensionsDecorator.ts @@ -1,5 +1,5 @@ -import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; -import { LambdaInterface } from '@aws-lambda-powertools/commons'; +import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics'; +import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; const metrics = new Metrics({ namespace: 'serverlessAirline', @@ -11,7 +11,7 @@ export class Lambda implements LambdaInterface { // Decorate your handler class method @metrics.logMetrics({ defaultDimensions: DEFAULT_DIMENSIONS }) public async handler(_event: unknown, _context: unknown): Promise { - metrics.addMetric('successfulBooking', MetricUnits.Count, 1); + metrics.addMetric('successfulBooking', MetricUnit.Count, 1); } } diff --git a/docs/snippets/metrics/defaultDimensionsMiddy.ts b/docs/snippets/metrics/defaultDimensionsMiddy.ts index b75ed56a6b..b5f7ec9256 100644 --- a/docs/snippets/metrics/defaultDimensionsMiddy.ts +++ b/docs/snippets/metrics/defaultDimensionsMiddy.ts @@ -1,8 +1,5 @@ -import { - Metrics, - MetricUnits, - logMetrics, -} from '@aws-lambda-powertools/metrics'; +import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics'; +import { logMetrics } from '@aws-lambda-powertools/metrics/middleware'; import middy from '@middy/core'; const metrics = new Metrics({ @@ -14,7 +11,7 @@ const lambdaHandler = async ( _event: unknown, _context: unknown ): Promise => { - metrics.addMetric('successfulBooking', MetricUnits.Count, 1); + metrics.addMetric('successfulBooking', MetricUnit.Count, 1); }; // Wrap the handler with middy diff --git a/docs/snippets/metrics/manual.ts b/docs/snippets/metrics/manual.ts index d64a3b5393..79c0068ca8 100644 --- a/docs/snippets/metrics/manual.ts +++ b/docs/snippets/metrics/manual.ts @@ -1,4 +1,4 @@ -import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; +import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics'; const metrics = new Metrics({ namespace: 'serverlessAirline', @@ -9,6 +9,6 @@ export const handler = async ( _event: unknown, _context: unknown ): Promise => { - metrics.addMetric('successfulBooking', MetricUnits.Count, 10); + metrics.addMetric('successfulBooking', MetricUnit.Count, 10); metrics.publishStoredMetrics(); }; diff --git a/docs/snippets/metrics/middy.ts b/docs/snippets/metrics/middy.ts index 0a8330e931..d45a4aa08d 100644 --- a/docs/snippets/metrics/middy.ts +++ b/docs/snippets/metrics/middy.ts @@ -1,8 +1,5 @@ -import { - Metrics, - MetricUnits, - logMetrics, -} from '@aws-lambda-powertools/metrics'; +import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics'; +import { logMetrics } from '@aws-lambda-powertools/metrics/middleware'; import middy from '@middy/core'; const metrics = new Metrics({ @@ -14,7 +11,7 @@ const lambdaHandler = async ( _event: unknown, _context: unknown ): Promise => { - metrics.addMetric('successfulBooking', MetricUnits.Count, 1); + metrics.addMetric('successfulBooking', MetricUnit.Count, 1); }; export const handler = middy(lambdaHandler).use(logMetrics(metrics)); diff --git a/docs/snippets/metrics/multiValueMetrics.ts b/docs/snippets/metrics/multiValueMetrics.ts index 6614e39409..be185d0718 100644 --- a/docs/snippets/metrics/multiValueMetrics.ts +++ b/docs/snippets/metrics/multiValueMetrics.ts @@ -1,4 +1,4 @@ -import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; +import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics'; const metrics = new Metrics({ namespace: 'serverlessAirline', @@ -9,7 +9,7 @@ export const handler = async ( _event: unknown, _context: unknown ): Promise => { - metrics.addMetric('performedActionA', MetricUnits.Count, 2); + metrics.addMetric('performedActionA', MetricUnit.Count, 2); // do something else... - metrics.addMetric('performedActionA', MetricUnits.Count, 1); + metrics.addMetric('performedActionA', MetricUnit.Count, 1); }; diff --git a/docs/snippets/metrics/sam.ts b/docs/snippets/metrics/sam.ts index 79cb23e522..999e3fd9e3 100644 --- a/docs/snippets/metrics/sam.ts +++ b/docs/snippets/metrics/sam.ts @@ -1,8 +1,8 @@ -import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; +import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics'; // Metrics parameters fetched from the environment variables (see template.yaml tab) const metrics = new Metrics(); -metrics.addMetric('successfulBooking', MetricUnits.Count, 1); +metrics.addMetric('successfulBooking', MetricUnit.Count, 1); // You can also pass the parameters in the constructor // const metrics = new Metrics({ diff --git a/docs/snippets/metrics/setDefaultDimensions.ts b/docs/snippets/metrics/setDefaultDimensions.ts index ddb54f7691..7125519d54 100644 --- a/docs/snippets/metrics/setDefaultDimensions.ts +++ b/docs/snippets/metrics/setDefaultDimensions.ts @@ -1,4 +1,4 @@ -import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; +import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics'; const metrics = new Metrics({ namespace: 'serverlessAirline', @@ -10,5 +10,5 @@ export const handler = async ( _event: unknown, _context: unknown ): Promise => { - metrics.addMetric('successfulBooking', MetricUnits.Count, 1); + metrics.addMetric('successfulBooking', MetricUnit.Count, 1); }; diff --git a/docs/snippets/metrics/singleMetricDifferentDimsDecorator.ts b/docs/snippets/metrics/singleMetricDifferentDimsDecorator.ts index d7b811aa3b..44bc941bf4 100644 --- a/docs/snippets/metrics/singleMetricDifferentDimsDecorator.ts +++ b/docs/snippets/metrics/singleMetricDifferentDimsDecorator.ts @@ -1,5 +1,5 @@ -import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; -import { LambdaInterface } from '@aws-lambda-powertools/commons'; +import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics'; +import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; const metrics = new Metrics({ namespace: 'serverlessAirline', @@ -11,12 +11,12 @@ class Lambda implements LambdaInterface { public async handler(_event: unknown, _context: unknown): Promise { metrics.addDimension('metricUnit', 'milliseconds'); // This metric will have the "metricUnit" dimension, and no "metricType" dimension: - metrics.addMetric('latency', MetricUnits.Milliseconds, 56); + metrics.addMetric('latency', MetricUnit.Milliseconds, 56); const singleMetric = metrics.singleMetric(); // This metric will have the "metricType" dimension, and no "metricUnit" dimension: singleMetric.addDimension('metricType', 'business'); - singleMetric.addMetric('orderSubmitted', MetricUnits.Count, 1); + singleMetric.addMetric('orderSubmitted', MetricUnit.Count, 1); } } diff --git a/docs/snippets/metrics/singleMetricDifferentDimsMiddy.ts b/docs/snippets/metrics/singleMetricDifferentDimsMiddy.ts index 66642078df..1344455fc8 100644 --- a/docs/snippets/metrics/singleMetricDifferentDimsMiddy.ts +++ b/docs/snippets/metrics/singleMetricDifferentDimsMiddy.ts @@ -1,8 +1,5 @@ -import { - Metrics, - MetricUnits, - logMetrics, -} from '@aws-lambda-powertools/metrics'; +import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics'; +import { logMetrics } from '@aws-lambda-powertools/metrics/middleware'; import middy from '@middy/core'; const metrics = new Metrics({ @@ -16,12 +13,12 @@ const lambdaHandler = async ( ): Promise => { metrics.addDimension('metricUnit', 'milliseconds'); // This metric will have the "metricUnit" dimension, and no "metricType" dimension: - metrics.addMetric('latency', MetricUnits.Milliseconds, 56); + metrics.addMetric('latency', MetricUnit.Milliseconds, 56); const singleMetric = metrics.singleMetric(); // This metric will have the "metricType" dimension, and no "metricUnit" dimension: singleMetric.addDimension('metricType', 'business'); - singleMetric.addMetric('orderSubmitted', MetricUnits.Count, 1); + singleMetric.addMetric('orderSubmitted', MetricUnit.Count, 1); }; export const handler = middy(lambdaHandler).use(logMetrics(metrics)); diff --git a/docs/snippets/metrics/throwOnEmptyMetrics.ts b/docs/snippets/metrics/throwOnEmptyMetrics.ts index 8fc01ae4b3..2acb3f3dfd 100644 --- a/docs/snippets/metrics/throwOnEmptyMetrics.ts +++ b/docs/snippets/metrics/throwOnEmptyMetrics.ts @@ -1,8 +1,5 @@ -import { - Metrics, - MetricUnits, - logMetrics, -} from '@aws-lambda-powertools/metrics'; +import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics'; +import { logMetrics } from '@aws-lambda-powertools/metrics/middleware'; import middy from '@middy/core'; const metrics = new Metrics({ @@ -14,7 +11,7 @@ const lambdaHandler = async ( _event: unknown, _context: unknown ): Promise => { - metrics.addMetric('successfulBooking', MetricUnits.Count, 1); + metrics.addMetric('successfulBooking', MetricUnit.Count, 1); }; export const handler = middy(lambdaHandler).use( diff --git a/docs/snippets/package.json b/docs/snippets/package.json index e017b77ff0..415dfccb3c 100644 --- a/docs/snippets/package.json +++ b/docs/snippets/package.json @@ -1,11 +1,12 @@ { "name": "docs", - "version": "1.14.0", + "version": "2.0.2", "description": "A collection code snippets for the Powertools for AWS Lambda (TypeScript) docs", "author": { "name": "Amazon Web Services", "url": "https://aws.amazon.com" }, + "private": true, "scripts": { "test": "echo 'Not Applicable'", "test:e2e": "echo 'Not Applicable'", @@ -28,15 +29,15 @@ }, "homepage": "https://github.com/aws-powertools/powertools-lambda-typescript#readme", "devDependencies": { - "@aws-sdk/client-appconfigdata": "^3.413.0", - "@aws-sdk/client-dynamodb": "^3.413.0", - "@aws-sdk/client-secrets-manager": "^3.413.0", - "@aws-sdk/client-ssm": "^3.413.0", - "@aws-sdk/util-dynamodb": "^3.413.0", - "aws-sdk": "^2.1458.0", - "aws-sdk-client-mock": "^3.0.0", - "aws-sdk-client-mock-jest": "^3.0.0", - "axios": "^1.5.0", + "@aws-sdk/client-appconfigdata": "^3.525.0", + "@aws-sdk/client-dynamodb": "^3.525.0", + "@aws-sdk/client-secrets-manager": "^3.525.0", + "@aws-sdk/client-ssm": "^3.525.0", + "@aws-sdk/util-dynamodb": "^3.525.0", + "aws-sdk": "^2.1568.0", + "aws-sdk-client-mock": "^3.0.1", + "aws-sdk-client-mock-jest": "^3.0.1", + "axios": "^1.6.7", "hashi-vault-js": "^0.4.14", "zod": "^3.22.4" } diff --git a/docs/snippets/parameters/appConfigProviderCustomClient.ts b/docs/snippets/parameters/appConfigProviderCustomClient.ts index d4315fb58c..887fcc765a 100644 --- a/docs/snippets/parameters/appConfigProviderCustomClient.ts +++ b/docs/snippets/parameters/appConfigProviderCustomClient.ts @@ -5,6 +5,8 @@ import { AppConfigDataClient } from '@aws-sdk/client-appconfigdata'; const appConfigClient = new AppConfigDataClient({ region: 'us-east-1' }); // pass the client to the provider const configsProvider = new AppConfigProvider({ + application: 'my-app', + environment: 'my-env', awsSdkV3Client: appConfigClient, }); diff --git a/docs/snippets/parameters/customProviderVault.ts b/docs/snippets/parameters/customProviderVault.ts index 9fea8f22aa..91490f45a7 100644 --- a/docs/snippets/parameters/customProviderVault.ts +++ b/docs/snippets/parameters/customProviderVault.ts @@ -1,7 +1,6 @@ import { Logger } from '@aws-lambda-powertools/logger'; import { BaseProvider } from '@aws-lambda-powertools/parameters/base'; import Vault from 'hashi-vault-js'; -import { isErrorResponse } from './customProviderVaultTypes'; import type { HashiCorpVaultProviderOptions, HashiCorpVaultGetOptions, @@ -18,7 +17,9 @@ class HashiCorpVaultProvider extends BaseProvider { * @param {HashiCorpVaultProviderOptions} config - The configuration object. */ public constructor(config: HashiCorpVaultProviderOptions) { - super(); + super({ + proto: Vault, + }); const { url, token, clientConfig, vaultClient } = config; if (vaultClient) { @@ -28,7 +29,7 @@ class HashiCorpVaultProvider extends BaseProvider { throw Error('Not a valid Vault client provided'); } } else { - const config: Vault.VaultConfig = { + const config = { baseUrl: url, ...(clientConfig ?? { timeout: 10000, @@ -90,7 +91,7 @@ class HashiCorpVaultProvider extends BaseProvider { mount ); - if (isErrorResponse(response)) { + if (response.isVaultError) { this.#logger.error('An error occurred', { error: response.vaultHelpMessage, }); diff --git a/docs/snippets/parameters/customProviderVaultTypes.ts b/docs/snippets/parameters/customProviderVaultTypes.ts index 09845d3cbd..ac5d99ac4a 100644 --- a/docs/snippets/parameters/customProviderVaultTypes.ts +++ b/docs/snippets/parameters/customProviderVaultTypes.ts @@ -1,5 +1,5 @@ import { GetOptionsInterface } from '@aws-lambda-powertools/parameters/base/types'; -import type Vault from 'hashi-vault-js'; +import Vault from 'hashi-vault-js'; /** * Base interface for HashiCorpVaultProviderOptions. @@ -26,7 +26,7 @@ interface HashiCorpVaultProviderOptionsWithClientConfig /** * Optional configuration to pass during client initialization to customize the `hashi-vault-js` client. */ - clientConfig?: Omit; + clientConfig?: unknown; /** * This property should never be passed. */ @@ -83,15 +83,4 @@ interface HashiCorpVaultGetOptions extends GetOptionsInterface { sdkOptions?: HashiCorpVaultReadKVSecretOptions; } -/** - * Typeguard that discriminates the type of the response and excludes the ErrorResponse type. - * - * @param object The response object to discriminate - */ -export const isErrorResponse = ( - object: Vault.ReadKVSecretResponse -): object is Vault.ErrorResponse => { - return 'isVaultError' in object; -}; - export type { HashiCorpVaultProviderOptions, HashiCorpVaultGetOptions }; diff --git a/docs/snippets/parameters/dynamoDBProviderCustomClient.ts b/docs/snippets/parameters/dynamoDBProviderCustomClient.ts index 2eb94ef190..ef9d2af2a0 100644 --- a/docs/snippets/parameters/dynamoDBProviderCustomClient.ts +++ b/docs/snippets/parameters/dynamoDBProviderCustomClient.ts @@ -4,7 +4,10 @@ import { DynamoDBClient } from '@aws-sdk/client-dynamodb'; // construct your clients with any custom configuration const dynamoDBClient = new DynamoDBClient({ region: 'us-east-1' }); // pass the client to the provider -const valuesProvider = new DynamoDBProvider({ awsSdkV3Client: dynamoDBClient }); +const valuesProvider = new DynamoDBProvider({ + tableName: 'my-table', + awsSdkV3Client: dynamoDBClient, +}); export const handler = async (): Promise => { // Retrieve a single value diff --git a/docs/snippets/parameters/testingYourCodeProvidersJestMock.ts b/docs/snippets/parameters/testingYourCodeProvidersJestMock.ts index 96d4d025d9..b93062e765 100644 --- a/docs/snippets/parameters/testingYourCodeProvidersJestMock.ts +++ b/docs/snippets/parameters/testingYourCodeProvidersJestMock.ts @@ -1,5 +1,6 @@ import { handler } from './testingYourCodeFunctionsHandler'; import { AppConfigProvider } from '@aws-lambda-powertools/parameters/appconfig'; +import { Uint8ArrayBlobAdapter } from '@smithy/util-stream'; describe('Function tests', () => { const providerSpy = jest.spyOn(AppConfigProvider.prototype, 'get'); @@ -16,7 +17,9 @@ describe('Function tests', () => { name: 'paywall', }, }; - providerSpy.mockResolvedValueOnce(expectedConfig); + providerSpy.mockResolvedValueOnce( + Uint8ArrayBlobAdapter.fromString(JSON.stringify(expectedConfig)) + ); // Act const result = await handler({}, {}); diff --git a/docs/snippets/tracer/accessRootTraceId.ts b/docs/snippets/tracer/accessRootTraceId.ts index f868d8b5e2..2491f7530f 100644 --- a/docs/snippets/tracer/accessRootTraceId.ts +++ b/docs/snippets/tracer/accessRootTraceId.ts @@ -5,7 +5,7 @@ const tracer = new Tracer({ serviceName: 'serverlessAirline' }); export const handler = async ( _event: unknown, _context: unknown -): Promise => { +): Promise => { try { } catch (err) { const rootTraceId = tracer.getRootXrayTraceId(); diff --git a/docs/snippets/tracer/captureMethodDecorator.ts b/docs/snippets/tracer/captureMethodDecorator.ts index 1b15cf44c7..809a87fd2a 100644 --- a/docs/snippets/tracer/captureMethodDecorator.ts +++ b/docs/snippets/tracer/captureMethodDecorator.ts @@ -1,5 +1,5 @@ import { Tracer } from '@aws-lambda-powertools/tracer'; -import { LambdaInterface } from '@aws-lambda-powertools/commons'; +import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; const tracer = new Tracer({ serviceName: 'serverlessAirline' }); diff --git a/docs/snippets/tracer/decorator.ts b/docs/snippets/tracer/decorator.ts index 616c3eb63d..985b82bde5 100644 --- a/docs/snippets/tracer/decorator.ts +++ b/docs/snippets/tracer/decorator.ts @@ -1,5 +1,5 @@ import { Tracer } from '@aws-lambda-powertools/tracer'; -import { LambdaInterface } from '@aws-lambda-powertools/commons'; +import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; const tracer = new Tracer({ serviceName: 'serverlessAirline' }); diff --git a/docs/snippets/tracer/disableCaptureResponseHandler.ts b/docs/snippets/tracer/disableCaptureResponseHandler.ts index 9a08a31dcc..2c35dfb080 100644 --- a/docs/snippets/tracer/disableCaptureResponseHandler.ts +++ b/docs/snippets/tracer/disableCaptureResponseHandler.ts @@ -1,5 +1,5 @@ import { Tracer } from '@aws-lambda-powertools/tracer'; -import { LambdaInterface } from '@aws-lambda-powertools/commons'; +import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; const tracer = new Tracer({ serviceName: 'serverlessAirline' }); diff --git a/docs/snippets/tracer/disableCaptureResponseMethod.ts b/docs/snippets/tracer/disableCaptureResponseMethod.ts index 26b6e2519a..9633608907 100644 --- a/docs/snippets/tracer/disableCaptureResponseMethod.ts +++ b/docs/snippets/tracer/disableCaptureResponseMethod.ts @@ -1,4 +1,4 @@ -import { LambdaInterface } from '@aws-lambda-powertools/commons'; +import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; import { Tracer } from '@aws-lambda-powertools/tracer'; const tracer = new Tracer({ serviceName: 'serverlessAirline' }); diff --git a/docs/snippets/tracer/disableCaptureResponseMiddy.ts b/docs/snippets/tracer/disableCaptureResponseMiddy.ts index 82aa1b345c..5af7ec2342 100644 --- a/docs/snippets/tracer/disableCaptureResponseMiddy.ts +++ b/docs/snippets/tracer/disableCaptureResponseMiddy.ts @@ -1,4 +1,5 @@ -import { Tracer, captureLambdaHandler } from '@aws-lambda-powertools/tracer'; +import { Tracer } from '@aws-lambda-powertools/tracer'; +import { captureLambdaHandler } from '@aws-lambda-powertools/tracer/middleware'; import middy from '@middy/core'; const tracer = new Tracer({ serviceName: 'serverlessAirline' }); diff --git a/docs/snippets/tracer/middy.ts b/docs/snippets/tracer/middy.ts index 22fe705619..591b9ff00d 100644 --- a/docs/snippets/tracer/middy.ts +++ b/docs/snippets/tracer/middy.ts @@ -1,4 +1,5 @@ -import { Tracer, captureLambdaHandler } from '@aws-lambda-powertools/tracer'; +import { Tracer } from '@aws-lambda-powertools/tracer'; +import { captureLambdaHandler } from '@aws-lambda-powertools/tracer/middleware'; import middy from '@middy/core'; const tracer = new Tracer({ serviceName: 'serverlessAirline' }); diff --git a/docs/upgrade.md b/docs/upgrade.md index 62437fb444..bc104bc099 100644 --- a/docs/upgrade.md +++ b/docs/upgrade.md @@ -3,14 +3,301 @@ title: Upgrade guide description: Guide to update between major Powertools for AWS Lambda (TypeScript) versions --- -## Migrate to v2 from v1 +## Migrate from v1 to v2 -This release includes some breaking changes, please take some time to review this guide to make your transition to v2 as smooth as possible. +V2 is focused on official support for ESM (ECMAScript modules). We've made other minimal breaking changes to make your transition to v2 as smooth as possible. ### Quick summary -!!! warning - This guide is a work in progress. We'll update it as we get closer to the 2.0 release. If you have any questions, or want to follow the progress, please join the discussion on the [GitHub issue](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1714). +| Area | Change | Code change required | +| --------------------- | ------------------------------------------------------------------------------------------------------------------------------ | -------------------- | +| **ESM support** | Added ESM support via dual CommonJS and ESM bundling, enabling top-level `await` and tree-shaking. | - | +| **Middy.js** | Updated import path for Middy.js middlewares to leverage subpath exports - i.e. `@aws-lambda-powertools/tracer/middleware`. | Yes | +| **Types imports** | Updated import path for TypeScript types to leverage subpath exports - i.e. `@aws-lambda-powertools/logger/types`. | Yes | +| **Logger** | Changed [log sampling](./core/logger.md#sampling-logs) to dynamically switch log level to `DEBUG` on a percentage of requests. | - | +| **Logger** | Updated [custom log formatter](#custom-log-formatter) to include standard as well as persistent keys. | Yes | +| **Logger and Tracer** | Removed deprecated `createLogger` and `createTracer` helper functions in favor of direct instantiation. | Yes | -| Area | Change | Code change required | -| ---- | ------ | -------------------- | \ No newline at end of file + +### First steps + +Before you start, we suggest making a copy of your current working project or create a new git branch. + +1. Upgrade Node.js to v16 or higher, Node.js v20 is recommended. +2. Ensure that you have the latest Powertools for AWS Lambda (TypeScript) version via [Lambda Layer](./index.md#lambda-layer) or npm. +3. Review the following sections to confirm whether they apply to your codebase. + +## ESM support + +With support for ES Modules in v2, you can now use `import` instead of `require` syntax. + +This is especially useful when you want to run asynchronous code during the initialization phase by using top-level `await`. + +```typescript title="top-level await example in v2" +import { getSecret } from '@aws-lambda-powertools/parameters/secrets'; + +// This code will run during the initialization phase of your Lambda function +const myApiKey = await getSecret('my-api-key', { transform: 'json' }); + +export const handler = async (_event: unknown, _context: unknown) => { + // ... +}; +``` + +In v2, we improved tree-shaking support to help you reduce your function bundle size. We would love to hear your feedback on further improvements we could make. + +### Unable to use ESM? + +!!! note "We recommend using ESM for the best experience _(top-level await, smaller bundle size etc.)_." + +If you're unable to use ESM, you can still use the `require` syntax to import the package. We will continue to support it by shipping CommonJS modules alongside ESM. + +You might still need the `require` syntax when using a dependency or a transitive dependency that doesn't support ESM. For example, Tracer _(`@aws-lambda-powertools/tracer`)_ relies on the AWS X-Ray SDK for Node.js which uses `require`. + +When that happens, you can instruct your bundler to use the `require` syntax for specific dependencies while using ESM for everything else. This is commonly known as [polyfill](https://developer.mozilla.org/en-US/docs/Glossary/Polyfill){target="_blank"}. +Here is an example using `esbuild` bundler. + +=== "With AWS CDK" + + ```typescript hl_lines="15 20-21" + import { Stack, type StackProps } from 'aws-cdk-lib'; + import { Construct } from 'constructs'; + import { NodejsFunction, OutputFormat } from 'aws-cdk-lib/aws-lambda-nodejs'; + import { Runtime } from 'aws-cdk-lib/aws-lambda'; + + export class MyStack extends Stack { + public constructor(scope: Construct, id: string, props?: StackProps) { + super(scope, id, props); + + const handler = new NodejsFunction(this, 'helloWorldFunction', { + runtime: Runtime.NODEJS_20_X, + handler: 'handler', + entry: 'src/index.ts', + bundling: { + format: OutputFormat.ESM, + minify: true, + esbuildArgs: { + "--tree-shaking": "true", + }, + banner: + "import { createRequire } from 'module';const require = createRequire(import.meta.url);", // (1)! + }, + }); + } + } + ``` + + 1. `esbuild` will include this arbitrary code at the top of your bundle to maximize CommonJS compatibility _(`require` keyword)_. + +=== "With AWS SAM" + + ```yaml hl_lines="14 17-18" + Transform: AWS::Serverless-2016-10-31 + Resources: + HelloWorldFunction: + Type: AWS::Serverless::Function + Properties: + Runtime: nodejs20.x + Handler: src/index.handler + Metadata: + BuildMethod: esbuild + BuildProperties: + Minify: true + Target: 'ES2020' + Sourcemap: true + Format: esm + EntryPoints: + - src/index.ts + Banner: + js: "import { createRequire } from 'module';const require = createRequire(import.meta.url);" # (1)! + + ``` + + 1. `esbuild` will include this arbitrary code at the top of your bundle to maximize CommonJS compatibility _(`require` keyword)_. + +## Scoped imports + +### Middy.js middleware imports + +???+ note "Disregard if you are not using Middy.js middlewares." + In v2, we've added support for subpath exports. This means if you don't import Middy.js middlewares, you will benefit from a smaller bundle size. + +In v1, you could import Middy.js middlewares from the default export of a package _(e.g., `logger`)_. For example, you'd import `injectLambdaContext` Logger middleware from `@aws-lambda-powertools/logger`. + +In v2, you can now import only the Middy.js middlewares you want to use from a subpath export, _e.g., `@aws-lambda-powertools/logger/middleware`_, leading to a smaller bundle size. + +=== "Before" + + ```typescript + import { Logger, injectLambdaContext } from '@aws-lambda-powertools/logger'; + import { Tracer, captureLambdaHandler } from '@aws-lambda-powertools/tracer'; + import { Metrics, logMetrics } from '@aws-lambda-powertools/metrics'; + ``` + +=== "After" + + ```typescript hl_lines="2 5 8" + import { Logger } from '@aws-lambda-powertools/logger'; + import { injectLambdaContext } from '@aws-lambda-powertools/logger/middleware'; + + import { Tracer } from '@aws-lambda-powertools/tracer'; + import { captureLambdaHandler } from '@aws-lambda-powertools/tracer/middleware'; + + import { Metrics } from '@aws-lambda-powertools/metrics'; + import { logMetrics } from '@aws-lambda-powertools/metrics/middleware'; + ``` + +### Types imports + +In v1, you could import package types from each package under `/lib`, for example `@aws-lambda-powertools/logger/lib/types`. + +In v2, you can now directly import from the `types` subpath export, e.g., `@aws-lambda-powertools/logger/types`. This will optimize your bundle size, standardize types import across packages, future-proofing growth. + +=== "Before" + + ```typescript + import { LogAttributes, UnformattedAttributes } from '@aws-lambda-powertools/logger/lib/types'; + ``` + +=== "After" + + ```typescript + import { LogAttributes, UnformattedAttributes } from '@aws-lambda-powertools/logger/types'; + ``` + +## Logger + +### Log sampling + +!!! note "Disregard if you are not using the [log sampling feature](./core/logger.md#sampling-logs)." + +In v1, log sampling implementation was inconsistent from other Powertools for AWS Lambda languages _(Python, .NET, and Java)_. + +In v2, we changed these behaviors for consistency across languages: + +| Behavior | v1 | v2 | +| ----------------------- | ------------------------------------------------------------ | --------------------------------------------- | +| Log Level | Log level remains unchanged but any log statement is printed | Log level changes to `DEBUG` | +| Log sampling indication | No indication | Debug message indicates sampling is in effect | + +Logger `sampleRateValue` **continues** to determine the percentage of concurrent/cold start invocations that logs will be sampled, _e.g., log level set to `DEBUG`_. + +### Custom log formatter + +!!! note "Disregard if you are not customizing log output with a [custom log formatter](./core/logger.md#custom-log-formatter-bring-your-own-formatter)." + +In v1, `Logger` exposed the [standard](./core/logger.md#standard-structured-keys) as a single argument, _e.g., `formatAttributes(attributes: UnformattedAttributes)`_. It expected a plain object with keys and values you wanted in the final log output. + +In v2, you have more control over **standard** (`attributes`) and [**custom keys**](./core/logger.md#appending-persistent-additional-log-keys-and-values) (`additionalLogAttributes`) in the `formatAttributes` method. Also, you now return a `LogItem` object to increase type safety when defining the final log output. + +=== "Before" + + ```typescript hl_lines="5 8" + import { LogFormatter } from '@aws-lambda-powertools/logger'; + import { + LogAttributes, + UnformattedAttributes, + } from '@aws-lambda-powertools/logger/lib/types'; + + class MyCompanyLogFormatter extends LogFormatter { + public formatAttributes(attributes: UnformattedAttributes): LogAttributes { + return { + message: attributes.message, + service: attributes.serviceName, + environment: attributes.environment, + awsRegion: attributes.awsRegion, + correlationIds: { + awsRequestId: attributes.lambdaContext?.awsRequestId, + xRayTraceId: attributes.xRayTraceId, + }, + lambdaFunction: { + name: attributes.lambdaContext?.functionName, + arn: attributes.lambdaContext?.invokedFunctionArn, + memoryLimitInMB: attributes.lambdaContext?.memoryLimitInMB, + version: attributes.lambdaContext?.functionVersion, + coldStart: attributes.lambdaContext?.coldStart, + }, + logLevel: attributes.logLevel, + timestamp: this.formatTimestamp(attributes.timestamp), + logger: { + sampleRateValue: attributes.sampleRateValue, + }, + }; + } + } + + export { MyCompanyLogFormatter }; + ``` + +=== "After" + + ```typescript hl_lines="1-2 5-8" + import { LogFormatter, LogItem } from '@aws-lambda-powertools/logger'; + import type { LogAttributes, UnformattedAttributes } from '@aws-lambda-powertools/logger/types'; + + class MyCompanyLogFormatter extends LogFormatter { + public formatAttributes( + attributes: UnformattedAttributes, + additionalLogAttributes: LogAttributes // (1)! + ): LogItem { // (2)! + const baseAttributes = { + message: attributes.message, + service: attributes.serviceName, + environment: attributes.environment, + awsRegion: attributes.awsRegion, + correlationIds: { + awsRequestId: attributes.lambdaContext?.awsRequestId, + xRayTraceId: attributes.xRayTraceId, + }, + lambdaFunction: { + name: attributes.lambdaContext?.functionName, + arn: attributes.lambdaContext?.invokedFunctionArn, + memoryLimitInMB: attributes.lambdaContext?.memoryLimitInMB, + version: attributes.lambdaContext?.functionVersion, + coldStart: attributes.lambdaContext?.coldStart, + }, + logLevel: attributes.logLevel, + timestamp: this.formatTimestamp(attributes.timestamp), + logger: { + sampleRateValue: attributes.sampleRateValue, + }, + }; + + // Create a new LogItem with the base attributes + const logItem = new LogItem({ attributes: baseAttributes }); + + // Merge additional attributes + logItem.addAttributes(additionalLogAttributes); // (3)! + + return logItem; + } + } + + export { MyCompanyLogFormatter }; + ``` + + 1. This new argument contains all [your custom keys](./core/logger.md#appending-persistent-additional-log-keys-and-values). + 2. `LogItem` is the new return object instead of a plain object. + 3. If you prefer adding at the initialization, use:

**`LogItem({persistentAttributes: additionalLogAttributes, attributes: baseAttributes})`** + +## Helper functions + +We removed the deprecated `createLogger` and `createTracer` heper functions. + +```typescript +import { createLogger } from '@aws-lambda-powertools/logger'; +import { createTracer } from '@aws-lambda-powertools/tracer'; + +const logger = createLogger({ logLevel: 'info' }); +const tracer = createTracer({ serviceName: 'my-service' }); +``` + +You can migrate to instantiating the `Logger` and `Tracer` classes directly with no additional changes. + +```typescript +import { Logger } from '@aws-lambda-powertools/logger'; +import { Tracer } from '@aws-lambda-powertools/tracer'; + +const logger = new Logger({ logLevel: 'info' }); +const tracer = new Tracer({ serviceName: 'my-service' }); +``` diff --git a/docs/utilities/batch.md b/docs/utilities/batch.md index 5c2b5631f1..486d7c12a0 100644 --- a/docs/utilities/batch.md +++ b/docs/utilities/batch.md @@ -64,6 +64,13 @@ This behavior changes when you enable [ReportBatchItemFailures feature](https:// ## Getting started +### Installation + +Install the library in your project +```shell +npm i @aws-lambda-powertools/batch +``` + For this feature to work, you need to **(1)** configure your Lambda function event source to use `ReportBatchItemFailures`, and **(2)** return [a specific response](https://docs.aws.amazon.com/lambda/latest/dg/with-sqs.html#services-sqs-batchfailurereporting){target="_blank" rel="nofollow"} to report which records failed to be processed. Use your preferred deployment framework to set the correct configuration while this utility handles the correct response to be returned. diff --git a/docs/utilities/idempotency.md b/docs/utilities/idempotency.md index dc58487016..9629616bc1 100644 --- a/docs/utilities/idempotency.md +++ b/docs/utilities/idempotency.md @@ -56,11 +56,11 @@ Install the library in your project npm i @aws-lambda-powertools/idempotency @aws-sdk/client-dynamodb @aws-sdk/lib-dynamodb ``` -While we support Amazon DynamoDB as a persistance layer out of the box, you need to bring your own AWS SDK for JavaScript v3 DynamoDB client. +While we support Amazon DynamoDB as a persistence layer out of the box, you need to bring your own AWS SDK for JavaScript v3 DynamoDB client. ???+ note - This utility supports **[AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/){target="_blank"} only**. If you are using the `nodejs18.x` runtime, the AWS SDK for JavaScript v3 is already installed and you can install only the utility. + This utility supports **[AWS SDK for JavaScript v3](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/){target="_blank"} only**. If you are using the `nodejs18.x` runtime or newer, the AWS SDK for JavaScript v3 is already installed and you can install only the utility. ### IAM Permissions @@ -109,10 +109,11 @@ If you're not [changing the default configuration for the DynamoDB persistence l Larger items cannot be written to DynamoDB and will cause exceptions. ???+ info "Info: DynamoDB" - Each function invocation will generally make 2 requests to DynamoDB. If the - result returned by your Lambda is less than 1kb, you can expect 2 WCUs per invocation. For retried invocations, you will - see 1WCU and 1RCU. Review the [DynamoDB pricing documentation](https://aws.amazon.com/dynamodb/pricing/){target="_blank"} to - estimate the cost. + Each function invocation will make only 1 request to DynamoDB by using DynamoDB's [conditional expressions](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ConditionExpressions.html){target="_blank"} to ensure that we don't overwrite existing records, + and [ReturnValuesOnConditionCheckFailure](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html#DDB-PutItem-request-ReturnValuesOnConditionCheckFailure){target="_blank"} to return the record if it exists. + See [AWS Blog post on handling conditional write errors](https://aws.amazon.com/blogs/database/handle-conditional-write-errors-in-high-concurrency-scenarios-with-amazon-dynamodb/) for more details. + For retried invocations, you will see 1WCU and 1RCU. + Review the [DynamoDB pricing documentation](https://aws.amazon.com/dynamodb/pricing/){target="_blank"} to estimate the cost. ### MakeIdempotent function wrapper @@ -164,6 +165,10 @@ The function this example has two arguments, note that while wrapping it with th You can also use the `@idempotent` decorator to make your Lambda handler idempotent, similar to the `makeIdempotent` function wrapper. +!!! info + The class method decorators in this project follow the experimental implementation enabled via the [`experimentalDecorators` compiler option](https://www.typescriptlang.org/tsconfig#experimentalDecorators) in TypeScript. Additionally, they are implemented in a way that fits asynchronous methods. When decorating a synchronous method, the decorator replaces its implementation with an asynchronous one causing the caller to have to `await` the now decorated method. + If this is not the desired behavior, you can use one of the other patterns to make your logic idempotent. + === "index.ts" ```typescript hl_lines="17" @@ -183,8 +188,8 @@ The configuration options for the `@idempotent` decorator are the same as the on ### MakeHandlerIdempotent Middy middleware !!! tip "A note about Middy" - Currently we support only Middy `v3.x` that you can install it by running `npm i @middy/core@~3`. - Check their docs to learn more about [Middy and its middleware stack](https://middy.js.org/docs/intro/getting-started){target="_blank"} as well as [best practices when working with Powertools](https://middy.js.org/docs/integrations/lambda-powertools#best-practices){target="_blank"}. + Currently we support only Middy `v3.x` that you can install it by running `npm i @middy/core@~3`. + Check their docs to learn more about [Middy and its middleware stack](https://middy.js.org/docs/intro/getting-started){target="_blank"} as well as [best practices when working with Powertools](https://middy.js.org/docs/integrations/lambda-powertools#best-practices){target="_blank"}. If you are using [Middy](https://middy.js.org){target="_blank"} as your middleware engine, you can use the `makeHandlerIdempotent` middleware to make your Lambda handler idempotent. Similar to the `makeIdempotent` function wrapper, you can quickly make your Lambda handler idempotent by initializing the `DynamoDBPersistenceLayer` class and using it with the `makeHandlerIdempotent` middleware. diff --git a/docs/utilities/parameters.md b/docs/utilities/parameters.md index c2b844376e..df89ef8a62 100644 --- a/docs/utilities/parameters.md +++ b/docs/utilities/parameters.md @@ -44,7 +44,7 @@ Depending on the provider you want to use, install the library and the correspon ``` ???+ tip - If you are using the `nodejs18.x` runtime, the AWS SDK for JavaScript v3 is already installed and you can install the utility only. + If you are using the `nodejs18.x` runtime or newer, the AWS SDK for JavaScript v3 is already installed and you can install the utility only. ### IAM Permissions diff --git a/docs/versioning.md b/docs/versioning.md new file mode 100644 index 0000000000..c8055f59f7 --- /dev/null +++ b/docs/versioning.md @@ -0,0 +1,63 @@ +--- +title: Versioning and maintenance policy +description: Versioning and maintenance policy for Powertools for AWS Lambda (TypeScript) +--- + + + +### Overview + +This document outlines the maintenance policy for Powertools for AWS Lambda and their underlying dependencies. AWS regularly provides Powertools for AWS Lambda with updates that may contain new features, enhancements, bug fixes, security patches, or documentation updates. Updates may also address changes with dependencies, language runtimes, and operating systems. Powertools for AWS Lambda is published to package managers (e.g. PyPi, NPM, Maven, NuGet), and are available as source code on GitHub. + +We recommend users to stay up-to-date with Powertools for AWS Lambda releases to keep up with the latest features, security updates, and underlying dependencies. Continued use of an unsupported Powertools for AWS Lambda version is not recommended and is done at the user’s discretion. + +!!! info "For brevity, we will interchangeably refer to Powertools for AWS Lambda (TypeScript) as "SDK" _(Software Development Toolkit)_." + +### Versioning + +Powertools for AWS Lambda release versions are in the form of X.Y.Z where X represents the major version. Increasing the major version of an SDK indicates that this SDK underwent significant and substantial changes to support new idioms and patterns in the language. Major versions are introduced when public interfaces _(e.g. classes, methods, types, etc.)_, behaviors, or semantics have changed. Applications need to be updated in order for them to work with the newest SDK version. It is important to update major versions carefully and in accordance with the upgrade guidelines provided by AWS. + +### SDK major version lifecycle + +The lifecycle for major Powertools for AWS Lambda versions consists of 5 phases, which are outlined below. + +* **Developer Preview** (Phase 0) - During this phase, SDKs are not supported, should not be used in production environments, and are meant for early access and feedback purposes only. It is possible for future releases to introduce breaking changes. Once AWS identifies a release to be a stable product, it may mark it as a Release Candidate. Release Candidates are ready for GA release unless significant bugs emerge, and will receive full AWS support. +* **General Availability (GA)** (Phase 1) - During this phase, SDKs are fully supported. AWS will provide regular SDK releases that include support for new features, enhancements, as well as bug and security fixes. AWS will support the GA version of an SDK for _at least 12 months_, unless otherwise specified. +* **Maintenance Announcement** (Phase 2) - AWS will make a public announcement at least 6 months before an SDK enters maintenance mode. During this period, the SDK will continue to be fully supported. Typically, maintenance mode is announced at the same time as the next major version is transitioned to GA. +* **Maintenance** (Phase 3) - During the maintenance mode, AWS limits SDK releases to address critical bug fixes and security issues only. An SDK will not receive API updates for new or existing services, or be updated to support new regions. Maintenance mode has a _default duration of 6 months_, unless otherwise specified. +* **End-of-Support** (Phase 4) - When an SDK reaches end-of support, it will no longer receive updates or releases. Previously published releases will continue to be available via public package managers and the code will remain on GitHub. The GitHub repository may be archived. Use of an SDK which has reached end-of-support is done at the user’s discretion. We recommend users upgrade to the new major version. + +!!! note "Please note that the timelines shown below are illustrative and not binding" + +![Maintenance policy timelines](https://docs.aws.amazon.com/images/sdkref/latest/guide/images/maint-policy.png) + +### Dependency lifecycle + +Most AWS SDKs have underlying dependencies, such as language runtimes, AWS Lambda runtime, or third party libraries and frameworks. These dependencies are typically tied to the language community or the vendor who owns that particular component. Each community or vendor publishes their own end-of-support schedule for their product. + +The following terms are used to classify underlying third party dependencies: + +* [**AWS Lambda Runtime**](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html): Examples include `nodejs20.x`, `python3.12`, etc. +* **Language Runtime**: Examples include Python 3.12, NodeJS 20, Java 17, .NET Core, etc. +* **Third party Library**: Examples include Pydantic, AWS X-Ray SDK, AWS Encryption SDK, Middy.js, etc. + +Powertools for AWS Lambda follows the [AWS Lambda Runtime deprecation policy cycle](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html#runtime-support-policy), when it comes to Language Runtime. This means we will stop supporting their respective deprecated Language Runtime _(e.g., `nodejs20.x`)_ without increasing the major SDK version. + +!!! note "AWS reserves the right to stop support for an underlying dependency without increasing the major SDK version" + +### Communication methods + +Maintenance announcements are communicated in several ways: + +* A pinned GitHub Request For Comments (RFC) issue indicating the campaign for the next major version. The RFC will outline the path to end-of-support, specify campaign timelines, and upgrade guidance. +* AWS SDK documentation, such as API reference documentation, user guides, SDK product marketing pages, and GitHub readme(s) are updated to indicate the campaign timeline and provide guidance on upgrading affected applications. +* Deprecation warnings are added to the SDKs, outlining the path to end-of-support and linking to the upgrade guide. + +To see the list of available major versions of Powertools for AWS Lambda and where they are in their maintenance lifecycle, see [version support matrix](#version-support-matrix) + +### Version support matrix + +| SDK | Major version | Current Phase | General Availability Date | Notes | +| ------------------------------------ | ------------- | ------------------------ | ------------------------- | ------------------------------------------------------------------------------------------------------- | +| Powertools for AWS Lambda TypeScript | 1.x | Maintenance Announcement | 07/15/2022 | See [v2 RFC](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1714) | +| Powertools for AWS Lambda TypeScript | 1.x | General Availability | 07/15/2022 | See [Release Notes](https://github.com/aws-powertools/powertools-lambda-typescript/releases/tag/v1.0.0) | diff --git a/examples/cdk/CHANGELOG.md b/examples/cdk/CHANGELOG.md index 51743f9e3c..2b94cf69f4 100644 --- a/examples/cdk/CHANGELOG.md +++ b/examples/cdk/CHANGELOG.md @@ -3,6 +3,62 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2.0.2 (2024-03-05) + +**Note:** Version bump only for package cdk-sample + + + + + +## 2.0.1 (2024-03-04) + +**Note:** Version bump only for package cdk-sample + + + + + +# [2.0.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.18.1...v2.0.0) (2024-03-04) + +**Note:** Version bump only for package cdk-sample + + + + + +## 1.18.1 (2024-02-20) + +**Note:** Version bump only for package cdk-sample + +## [1.18.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.17.0...v1.18.0) (2024-01-26) + +**Note:** Version bump only for package cdk-sample + +## [1.17.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.16.0...v1.17.0) (2023-11-24) + +**Note:** Version bump only for package cdk-sample + +# [1.16.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.15.0...v1.16.0) (2023-11-16) + +### Features + +- **logger:** add support for `AWS_LAMBDA_LOG_LEVEL` and `POWERTOOLS_LOG_LEVEL` ([#1795](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1795)) ([e69abfb](https://github.com/aws-powertools/powertools-lambda-typescript/commit/e69abfb5f1b5d3bf993ac2fe66fae85a85af9905)) + +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) + +## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) + +**Note:** Version bump only for package cdk-sample + +## [1.14.1](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.0...v1.14.1) (2023-10-31) + +**Note:** Version bump only for package cdk-sample + # [1.14.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.13.1...v1.14.0) (2023-09-29) **Note:** Version bump only for package cdk-sample diff --git a/examples/cdk/package.json b/examples/cdk/package.json index 0f8daae847..cbdb13d0c5 100644 --- a/examples/cdk/package.json +++ b/examples/cdk/package.json @@ -1,6 +1,6 @@ { "name": "cdk-sample", - "version": "1.14.0", + "version": "2.0.2", "author": { "name": "Amazon Web Services", "url": "https://aws.amazon.com" @@ -25,27 +25,28 @@ "*.js": "npm run lint-fix" }, "devDependencies": { - "@aws-lambda-powertools/commons": "^1.14.0", - "@aws-lambda-powertools/logger": "^1.14.0", - "@aws-lambda-powertools/metrics": "^1.14.0", - "@aws-lambda-powertools/parameters": "^1.14.0", - "@aws-lambda-powertools/tracer": "^1.14.0", - "@aws-sdk/client-ssm": "^3.413.0", - "@aws-sdk/lib-dynamodb": "^3.413.0", - "@types/aws-lambda": "^8.10.121", - "@types/jest": "^29.5.4", - "@types/node": "20.6.1", - "aws-cdk": "^2.96.1", - "esbuild": "^0.19.3", + "@aws-lambda-powertools/commons": "^2.0.2", + "@aws-lambda-powertools/logger": "^2.0.2", + "@aws-lambda-powertools/metrics": "^2.0.2", + "@aws-lambda-powertools/parameters": "^2.0.2", + "@aws-lambda-powertools/tracer": "^2.0.2", + "@aws-sdk/client-ssm": "^3.525.0", + "@aws-sdk/lib-dynamodb": "^3.525.0", + "@types/aws-lambda": "^8.10.134", + "@types/jest": "^29.5.12", + "@types/node": "20.11.24", + "aws-cdk": "^2.130.0", + "constructs": "^10.3.0", + "esbuild": "^0.20.1", "jest": "^29.7.0", - "ts-jest": "^29.1.1", - "ts-node": "^10.9.1", - "typescript": "^5.2.2" + "ts-jest": "^29.1.2", + "ts-node": "^10.9.2", + "typescript": "^5.3.3" }, "dependencies": { - "@middy/core": "^3.6.2", - "aws-cdk-lib": "^2.96.1", - "constructs": "^10.2.70", + "@middy/core": "^4.7.0", + "aws-cdk-lib": "^2.130.0", + "construct": "^1.0.0", "phin": "^3.7.0", "source-map-support": "^0.5.21" } diff --git a/examples/cdk/src/example-stack.ts b/examples/cdk/src/example-stack.ts index b7cfa0d9ed..9d5236c054 100644 --- a/examples/cdk/src/example-stack.ts +++ b/examples/cdk/src/example-stack.ts @@ -11,7 +11,7 @@ import { StringParameter } from 'aws-cdk-lib/aws-ssm'; import { Construct } from 'constructs'; const commonProps: Partial = { - runtime: Runtime.NODEJS_18_X, + runtime: Runtime.NODEJS_20_X, tracing: Tracing.ACTIVE, timeout: Duration.seconds(30), logRetention: RetentionDays.ONE_DAY, @@ -19,7 +19,7 @@ const commonProps: Partial = { NODE_OPTIONS: '--enable-source-maps', // see https://docs.aws.amazon.com/lambda/latest/dg/typescript-exceptions.html POWERTOOLS_SERVICE_NAME: 'items-store', POWERTOOLS_METRICS_NAMESPACE: 'PowertoolsCDKExample', - LOG_LEVEL: 'DEBUG', + POWERTOOLS_LOG_LEVEL: 'DEBUG', }, bundling: { externalModules: [ @@ -53,7 +53,7 @@ export class CdkAppStack extends Stack { 'powertools-layer', `arn:aws:lambda:${ Stack.of(this).region - }:094274105915:layer:AWSLambdaPowertoolsTypeScript:18` + }:094274105915:layer:AWSLambdaPowertoolsTypeScript:24` ) ); @@ -112,7 +112,7 @@ class UuidApi extends Construct { super(scope, id); const uuidFn = new NodejsFunction(this, 'UuidFn', { - runtime: Runtime.NODEJS_18_X, + runtime: Runtime.NODEJS_20_X, entry: './functions/uuid.ts', }); diff --git a/examples/sam/CHANGELOG.md b/examples/sam/CHANGELOG.md index 19f3883450..933c34b8b6 100644 --- a/examples/sam/CHANGELOG.md +++ b/examples/sam/CHANGELOG.md @@ -3,6 +3,65 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2.0.2 (2024-03-05) + +**Note:** Version bump only for package sam-example + + + + +## 2.0.1 (2024-03-04) + +**Note:** Version bump only for package sam-example + + + + + +# [2.0.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.18.1...v2.0.0) (2024-03-04) + +**Note:** Version bump only for package sam-example + + + + + +## 1.18.1 (2024-02-20) + +**Note:** Version bump only for package sam-example + + + + + +## [1.18.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.17.0...v1.18.0) (2024-01-26) + +**Note:** Version bump only for package sam-sample + +## [1.17.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.16.0...v1.17.0) (2023-11-24) + +**Note:** Version bump only for package sam-example + +# [1.16.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.15.0...v1.16.0) (2023-11-16) + +### Features + +- **logger:** add support for `AWS_LAMBDA_LOG_LEVEL` and `POWERTOOLS_LOG_LEVEL` ([#1795](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1795)) ([e69abfb](https://github.com/aws-powertools/powertools-lambda-typescript/commit/e69abfb5f1b5d3bf993ac2fe66fae85a85af9905)) + +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) + +## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) + +**Note:** Version bump only for package sam-example + +## [1.14.1](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.0...v1.14.1) (2023-10-31) + +**Note:** Version bump only for package sam-example + # [1.14.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.13.1...v1.14.0) (2023-09-29) **Note:** Version bump only for package sam-example diff --git a/examples/sam/package.json b/examples/sam/package.json index c8dc2a244a..499fc879c6 100644 --- a/examples/sam/package.json +++ b/examples/sam/package.json @@ -1,6 +1,6 @@ { "name": "sam-example", - "version": "1.14.0", + "version": "2.0.2", "author": { "name": "Amazon Web Services", "url": "https://aws.amazon.com" @@ -21,24 +21,24 @@ "*.js": "npm run lint-fix" }, "devDependencies": { - "@types/aws-lambda": "^8.10.121", - "@types/jest": "^29.5.4", - "@types/node": "20.6.1", + "@aws-sdk/client-dynamodb": "^3.525.0", + "@aws-sdk/client-ssm": "^3.525.0", + "@aws-sdk/lib-dynamodb": "^3.525.0", + "@types/aws-lambda": "^8.10.134", + "@types/jest": "^29.5.12", + "@types/node": "^20.11.24", + "esbuild": "^0.20.1", "jest": "^29.7.0", - "ts-jest": "^29.1.1", - "ts-node": "^10.9.1", - "typescript": "^5.2.2" + "ts-jest": "^29.1.2", + "ts-node": "^10.9.2", + "typescript": "^5.3.3" }, "dependencies": { - "@aws-lambda-powertools/logger": "^1.14.0", - "@aws-lambda-powertools/metrics": "^1.14.0", - "@aws-lambda-powertools/parameters": "^1.14.0", - "@aws-lambda-powertools/tracer": "^1.14.0", - "@aws-sdk/client-dynamodb": "^3.413.0", - "@aws-sdk/client-ssm": "^3.413.0", - "@aws-sdk/lib-dynamodb": "^3.413.0", - "@middy/core": "^3.6.2", - "esbuild": "^0.19.3", + "@aws-lambda-powertools/logger": "^2.0.2", + "@aws-lambda-powertools/metrics": "^2.0.2", + "@aws-lambda-powertools/parameters": "^2.0.2", + "@aws-lambda-powertools/tracer": "^2.0.2", + "@middy/core": "^4.7.0", "phin": "^3.7.0" } } \ No newline at end of file diff --git a/examples/sam/template.yaml b/examples/sam/template.yaml index 3f19a4c5d3..9596113f30 100644 --- a/examples/sam/template.yaml +++ b/examples/sam/template.yaml @@ -31,7 +31,7 @@ Parameters: # https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification-template-anatomy-globals.html Globals: Function: - Runtime: nodejs18.x + Runtime: nodejs20.x Architectures: - x86_64 MemorySize: 128 @@ -64,7 +64,7 @@ Resources: SAMPLE_TABLE: !Ref SampleTable POWERTOOLS_SERVICE_NAME: items-store POWERTOOLS_METRICS_NAMESPACE: PowertoolsSAMExample - LOG_LEVEL: Debug + POWERTOOLS_LOG_LEVEL: debug Events: Api: Type: Api @@ -104,7 +104,7 @@ Resources: SAMPLE_TABLE: !Ref SampleTable POWERTOOLS_SERVICE_NAME: items-store POWERTOOLS_METRICS_NAMESPACE: PowertoolsSAMExample - LOG_LEVEL: Debug + POWERTOOLS_LOG_LEVEL: debug Events: Api: Type: Api @@ -134,7 +134,7 @@ Resources: Variables: POWERTOOLS_SERVICE_NAME: items-store POWERTOOLS_METRICS_NAMESPACE: PowertoolsSAMExample - LOG_LEVEL: Debug + POWERTOOLS_LOG_LEVEL: debug # add ssm:getParameter permission to the function Policies: - SSMParameterWithSlashPrefixReadPolicy: @@ -186,7 +186,7 @@ Resources: SAMPLE_TABLE: !Ref SampleTable POWERTOOLS_SERVICE_NAME: items-store POWERTOOLS_METRICS_NAMESPACE: PowertoolsSAMExample - LOG_LEVEL: Debug + POWERTOOLS_LOG_LEVEL: debug Events: Api: Type: Api diff --git a/layers/CHANGELOG.md b/layers/CHANGELOG.md index c72ef7b6aa..d1b918ff64 100644 --- a/layers/CHANGELOG.md +++ b/layers/CHANGELOG.md @@ -3,6 +3,65 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2.0.2 (2024-03-05) + +**Note:** Version bump only for package layers + + + + + +## 2.0.1 (2024-03-04) + +**Note:** Version bump only for package layers + + + + + +# [2.0.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.18.1...v2.0.0) (2024-03-04) + +**Note:** Version bump only for package layers + + + + + +# 1.18.1 (2024-02-20) + +**Note:** Version bump only for package layers + + + + + +## [1.18.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.17.0...v1.18.0) (2024-01-26) + +**Note:** Version bump only for package layers + +## [1.17.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.16.0...v1.17.0) (2023-11-24) + +**Note:** Version bump only for package layers + +# [1.16.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.15.0...v1.16.0) (2023-11-16) + +**Note:** Version bump only for package layers + +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) +- **metrics:** log directly to stdout ([#1786](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1786)) ([75dc5b1](https://github.com/aws-powertools/powertools-lambda-typescript/commit/75dc5b1e16944416a287628c50ec4a0cf82c3023)) + +## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) + +**Note:** Version bump only for package layers + +## [1.14.1](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.0...v1.14.1) (2023-10-31) + +**Note:** Version bump only for package layers + # [1.14.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.13.1...v1.14.0) (2023-09-29) **Note:** Version bump only for package layers diff --git a/layers/bin/layers.ts b/layers/bin/layers.ts index bc7390c4fd..be4605b3e3 100644 --- a/layers/bin/layers.ts +++ b/layers/bin/layers.ts @@ -11,7 +11,7 @@ const app = new App(); new LayerPublisherStack(app, 'LayerPublisherStack', { powertoolsPackageVersion: app.node.tryGetContext('PowertoolsPackageVersion'), buildFromLocal: app.node.tryGetContext('BuildFromLocal') || false, - layerName: 'AWSLambdaPowertoolsTypeScript', + layerName: 'AWSLambdaPowertoolsTypeScriptV2', ssmParameterLayerArn: SSM_PARAM_LAYER_ARN, }); diff --git a/layers/package.json b/layers/package.json index 95dab12127..b2365d1ae8 100644 --- a/layers/package.json +++ b/layers/package.json @@ -1,6 +1,6 @@ { "name": "layers", - "version": "1.14.0", + "version": "2.0.2", "bin": { "layer": "bin/layers.js" }, @@ -39,8 +39,8 @@ "source-map-support": "^0.5.21" }, "dependencies": { - "aws-cdk": "^2.96.1", - "aws-cdk-lib": "^2.96.1", - "esbuild": "^0.19.3" + "aws-cdk": "^2.130.0", + "aws-cdk-lib": "^2.130.0", + "esbuild": "^0.20.1" } -} \ No newline at end of file +} diff --git a/layers/src/canary-stack.ts b/layers/src/canary-stack.ts index 342d5edb26..2d7aab1cee 100644 --- a/layers/src/canary-stack.ts +++ b/layers/src/canary-stack.ts @@ -64,7 +64,7 @@ export class CanaryStack extends Stack { SSM_PARAMETER_LAYER_ARN: props.ssmParameterLayerArn, }, layers: layer, - logRetention: RetentionDays.ONE_DAY, + logRetention: RetentionDays.TEN_YEARS, tracing: Tracing.ACTIVE, }); @@ -79,7 +79,7 @@ export class CanaryStack extends Stack { // use custom resource to trigger the lambda function during the CFN deployment const provider = new Provider(this, 'CanaryCustomResourceProvider', { onEventHandler: canaryFunction, - logRetention: RetentionDays.ONE_DAY, + logRetention: RetentionDays.TEN_YEARS, }); // random suffix forces recreation of the custom resource otherwise the custom resource will be reused from prevous deployment diff --git a/layers/src/layer-publisher-stack.ts b/layers/src/layer-publisher-stack.ts index 01148546db..49b2d87ede 100644 --- a/layers/src/layer-publisher-stack.ts +++ b/layers/src/layer-publisher-stack.ts @@ -36,14 +36,18 @@ export class LayerPublisherStack extends Stack { this.lambdaLayerVersion = new LayerVersion(this, 'LambdaPowertoolsLayer', { layerVersionName: props?.layerName, description: `Powertools for AWS Lambda (TypeScript) version ${powertoolsPackageVersion}`, - compatibleRuntimes: [Runtime.NODEJS_16_X, Runtime.NODEJS_18_X], + compatibleRuntimes: [ + Runtime.NODEJS_16_X, + Runtime.NODEJS_18_X, + Runtime.NODEJS_20_X, + ], license: 'MIT-0', // This is needed because the following regions do not support the compatibleArchitectures property #1400 // ...(![ 'eu-south-2', 'eu-central-2', 'ap-southeast-4' ].includes(Stack.of(this).region) ? { compatibleArchitectures: [Architecture.X86_64] } : {}), code: Code.fromAsset(resolve(__dirname), { bundling: { // This is here only because is required by CDK, however it is not used since the bundling is done locally - image: Runtime.NODEJS_18_X.bundlingImage, + image: Runtime.NODEJS_20_X.bundlingImage, // We need to run a command to generate a random UUID to force the bundling to run every time command: [`echo "${randomUUID()}"`], local: { @@ -104,7 +108,7 @@ export class LayerPublisherStack extends Stack { 'node_modules/@aws-sdk/**/README.md ', ]; const buildCommands: string[] = []; - // We need these modules because they are not included in the nodejs14x and nodejs16x runtimes + // We need these modules because they are not included in the nodejs16x runtimes const modulesToInstall: string[] = [ '@aws-sdk/client-dynamodb', '@aws-sdk/util-dynamodb', diff --git a/layers/tests/e2e/constants.ts b/layers/tests/e2e/constants.ts index e881a06b0e..b6b477031b 100644 --- a/layers/tests/e2e/constants.ts +++ b/layers/tests/e2e/constants.ts @@ -1,5 +1,5 @@ export const RESOURCE_NAME_PREFIX = 'Layers-E2E'; export const ONE_MINUTE = 60 * 1000; export const TEST_CASE_TIMEOUT = 3 * ONE_MINUTE; -export const SETUP_TIMEOUT = 5 * ONE_MINUTE; +export const SETUP_TIMEOUT = 7 * ONE_MINUTE; export const TEARDOWN_TIMEOUT = 5 * ONE_MINUTE; diff --git a/layers/tests/e2e/layerPublisher.test.ts b/layers/tests/e2e/layerPublisher.test.ts index 560015eee5..9f5535c9c0 100644 --- a/layers/tests/e2e/layerPublisher.test.ts +++ b/layers/tests/e2e/layerPublisher.test.ts @@ -145,10 +145,14 @@ describe(`Layers E2E tests, publisher stack`, () => { it( 'should have one info log related to coldstart metric', () => { - const logs = invocationLogs.getFunctionLogs('INFO'); + const logs = invocationLogs.getFunctionLogs(); + const emfLogEntry = logs.find((log) => + log.match( + /{"_aws":{"Timestamp":\d+,"CloudWatchMetrics":\[\{"Namespace":"\S+","Dimensions":\[\["service"\]\],"Metrics":\[\{"Name":"ColdStart","Unit":"Count"\}\]\}\]},"service":"\S+","ColdStart":1}/ + ) + ); - expect(logs.length).toBe(1); - expect(logs[0]).toContain('ColdStart'); + expect(emfLogEntry).toBeDefined(); }, TEST_CASE_TIMEOUT ); diff --git a/layers/tests/unit/layer-publisher.test.ts b/layers/tests/unit/layer-publisher.test.ts index 98b90788bd..bec61bc0f5 100644 --- a/layers/tests/unit/layer-publisher.test.ts +++ b/layers/tests/unit/layer-publisher.test.ts @@ -25,7 +25,7 @@ describe('Class: LayerPublisherStack', () => { // Assess template.resourceCountIs('AWS::Lambda::LayerVersion', 1); template.hasResourceProperties('AWS::Lambda::LayerVersion', { - CompatibleRuntimes: ['nodejs16.x', 'nodejs18.x'], + CompatibleRuntimes: ['nodejs16.x', 'nodejs18.x', 'nodejs20.x'], LicenseInfo: 'MIT-0', /* CompatibleArchitectures: [ 'x86_64', diff --git a/lerna.json b/lerna.json index ae57c9b49a..9beb95c0f1 100644 --- a/lerna.json +++ b/lerna.json @@ -13,7 +13,7 @@ "layers", "docs/snippets" ], - "version": "1.14.0", + "version": "2.0.2", "npmClient": "npm", "message": "chore(release): %s [skip ci]" } \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index a718ef0b15..953335527f 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -6,28 +6,29 @@ edit_uri: edit/main/docs nav: - Homepage: - - index.md - - Changelog: changelog.md - - API reference: api/" target="_blank - - Upgrade guide: upgrade.md - - We Made This (Community): we_made_this.md - - Roadmap: roadmap.md - - Features: - - core/tracer.md - - core/logger.md - - core/metrics.md - - utilities/parameters.md - - utilities/idempotency.md - - utilities/batch.md - - utilities/parser.md + - index.md + - Changelog: changelog.md + - API reference: api/" target="_blank + - Upgrade guide: upgrade.md + - We Made This (Community): we_made_this.md + - Roadmap: roadmap.md + - Features: + - core/tracer.md + - core/logger.md + - core/metrics.md + - utilities/parameters.md + - utilities/idempotency.md + - utilities/batch.md + - utilities/parser.md - Processes: - - Roadmap: roadmap.md - - Maintainers: maintainers.md - - Contributing: - - Development environment: contributing/setup.md - - Your first contribution: contributing/getting_started.md - - Conventions: contributing/conventions.md - - Testing: contributing/testing.md + - Roadmap: roadmap.md + - Versioning policy: versioning.md + - Maintainers: maintainers.md + - Contributing: + - Development environment: contributing/setup.md + - Your first contribution: contributing/getting_started.md + - Conventions: contributing/conventions.md + - Testing: contributing/testing.md theme: name: material diff --git a/package-lock.json b/package-lock.json index 07b8a5b164..237963475e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,31 +24,29 @@ "examples/sam" ], "devDependencies": { - "@middy/core": "^4.6.5", - "@types/aws-lambda": "^8.10.121", - "@types/jest": "^29.5.4", - "@types/node": "^20.6.1", - "@types/uuid": "^9.0.4", - "@typescript-eslint/eslint-plugin": "^6.7.0", - "@typescript-eslint/parser": "^6.7.0", - "eslint": "^8.49.0", - "eslint-config-prettier": "^9.0.0", + "@middy/core": "^4.7.0", + "@types/aws-lambda": "^8.10.134", + "@types/jest": "^29.5.12", + "@types/node": "^20.11.24", + "@typescript-eslint/eslint-plugin": "^6.21.0", + "@typescript-eslint/parser": "^6.21.0", + "eslint": "^8.57.0", + "eslint-config-prettier": "^9.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-import-resolver-typescript": "^3.6.0", - "eslint-plugin-import": "^2.28.1", - "eslint-plugin-prettier": "^5.0.0", - "husky": "^8.0.3", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "husky": "^9.0.11", "jest": "^29.7.0", "jest-runner-groups": "^2.2.0", - "lerna": "^7.3.0", - "lint-staged": "^14.0.1", - "prettier": "^3.0.3", - "rimraf": "^5.0.1", - "ts-jest": "^29.1.1", - "ts-node": "^10.9.1", - "typedoc": "^0.25.1", - "typedoc-plugin-missing-exports": "^2.1.0", - "typescript": "^5.2.2" + "lerna": "^8.1.2", + "lint-staged": "^15.2.2", + "prettier": "^3.2.5", + "ts-jest": "^29.1.2", + "ts-node": "^10.9.2", + "typedoc": "^0.25.8", + "typedoc-plugin-missing-exports": "^2.2.0", + "typescript": "^5.3.3" }, "engines": { "node": ">=16" @@ -56,29 +54,29 @@ }, "docs/snippets": { "name": "docs", - "version": "1.14.0", + "version": "2.0.2", "license": "MIT-0", "devDependencies": { - "@aws-sdk/client-appconfigdata": "^3.413.0", - "@aws-sdk/client-dynamodb": "^3.413.0", - "@aws-sdk/client-secrets-manager": "^3.413.0", - "@aws-sdk/client-ssm": "^3.413.0", - "@aws-sdk/util-dynamodb": "^3.413.0", - "aws-sdk": "^2.1458.0", - "aws-sdk-client-mock": "^3.0.0", - "aws-sdk-client-mock-jest": "^3.0.0", - "axios": "^1.5.0", + "@aws-sdk/client-appconfigdata": "^3.525.0", + "@aws-sdk/client-dynamodb": "^3.525.0", + "@aws-sdk/client-secrets-manager": "^3.525.0", + "@aws-sdk/client-ssm": "^3.525.0", + "@aws-sdk/util-dynamodb": "^3.525.0", + "aws-sdk": "^2.1568.0", + "aws-sdk-client-mock": "^3.0.1", + "aws-sdk-client-mock-jest": "^3.0.1", + "axios": "^1.6.7", "hashi-vault-js": "^0.4.14" } }, "examples/cdk": { "name": "cdk-sample", - "version": "1.14.0", + "version": "2.0.2", "license": "MIT-0", "dependencies": { - "@middy/core": "^3.6.2", - "aws-cdk-lib": "^2.96.1", - "constructs": "^10.2.70", + "@middy/core": "^4.7.0", + "aws-cdk-lib": "^2.130.0", + "construct": "^1.0.0", "phin": "^3.7.0", "source-map-support": "^0.5.21" }, @@ -86,85 +84,58 @@ "cdk-app": "bin/cdk-app.js" }, "devDependencies": { - "@aws-lambda-powertools/commons": "^1.14.0", - "@aws-lambda-powertools/logger": "^1.14.0", - "@aws-lambda-powertools/metrics": "^1.14.0", - "@aws-lambda-powertools/parameters": "^1.14.0", - "@aws-lambda-powertools/tracer": "^1.14.0", - "@aws-sdk/client-ssm": "^3.413.0", - "@aws-sdk/lib-dynamodb": "^3.413.0", - "@types/aws-lambda": "^8.10.121", - "@types/jest": "^29.5.4", - "@types/node": "20.6.1", - "aws-cdk": "^2.96.1", - "esbuild": "^0.19.3", + "@aws-lambda-powertools/commons": "^2.0.2", + "@aws-lambda-powertools/logger": "^2.0.2", + "@aws-lambda-powertools/metrics": "^2.0.2", + "@aws-lambda-powertools/parameters": "^2.0.2", + "@aws-lambda-powertools/tracer": "^2.0.2", + "@aws-sdk/client-ssm": "^3.525.0", + "@aws-sdk/lib-dynamodb": "^3.525.0", + "@types/aws-lambda": "^8.10.134", + "@types/jest": "^29.5.12", + "@types/node": "20.11.24", + "aws-cdk": "^2.130.0", + "constructs": "^10.3.0", + "esbuild": "^0.20.1", "jest": "^29.7.0", - "ts-jest": "^29.1.1", - "ts-node": "^10.9.1", - "typescript": "^5.2.2" - } - }, - "examples/cdk/node_modules/@middy/core": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/@middy/core/-/core-3.6.2.tgz", - "integrity": "sha512-/vyvG34RIt7CTmuB/jksGkk9vs6RCoOlRFPfdQq11dHkiKlT2mm8j/jZx7gSpEhXXh9LeaEMuKPnsgWBIlGS1g==", - "engines": { - "node": ">=14" + "ts-jest": "^29.1.2", + "ts-node": "^10.9.2", + "typescript": "^5.3.3" } }, - "examples/cdk/node_modules/@types/node": { - "version": "20.6.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.1.tgz", - "integrity": "sha512-4LcJvuXQlv4lTHnxwyHQZ3uR9Zw2j7m1C9DfuwoTFQQP4Pmu04O6IfLYgMmHoOCt0nosItLLZAH+sOrRE0Bo8g==", - "dev": true - }, "examples/sam": { "name": "sam-example", - "version": "1.14.0", + "version": "2.0.2", "license": "MIT-0", "dependencies": { - "@aws-lambda-powertools/logger": "^1.14.0", - "@aws-lambda-powertools/metrics": "^1.14.0", - "@aws-lambda-powertools/parameters": "^1.14.0", - "@aws-lambda-powertools/tracer": "^1.14.0", - "@aws-sdk/client-dynamodb": "^3.413.0", - "@aws-sdk/client-ssm": "^3.413.0", - "@aws-sdk/lib-dynamodb": "^3.413.0", - "@middy/core": "^3.6.2", - "esbuild": "^0.19.3", + "@aws-lambda-powertools/logger": "^2.0.2", + "@aws-lambda-powertools/metrics": "^2.0.2", + "@aws-lambda-powertools/parameters": "^2.0.2", + "@aws-lambda-powertools/tracer": "^2.0.2", + "@middy/core": "^4.7.0", "phin": "^3.7.0" }, "devDependencies": { - "@types/aws-lambda": "^8.10.121", - "@types/jest": "^29.5.4", - "@types/node": "20.6.1", + "@aws-sdk/client-dynamodb": "^3.525.0", + "@aws-sdk/client-ssm": "^3.525.0", + "@aws-sdk/lib-dynamodb": "^3.525.0", + "@types/aws-lambda": "^8.10.134", + "@types/jest": "^29.5.12", + "@types/node": "^20.11.24", + "esbuild": "^0.20.1", "jest": "^29.7.0", - "ts-jest": "^29.1.1", - "ts-node": "^10.9.1", - "typescript": "^5.2.2" - } - }, - "examples/sam/node_modules/@middy/core": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/@middy/core/-/core-3.6.2.tgz", - "integrity": "sha512-/vyvG34RIt7CTmuB/jksGkk9vs6RCoOlRFPfdQq11dHkiKlT2mm8j/jZx7gSpEhXXh9LeaEMuKPnsgWBIlGS1g==", - "engines": { - "node": ">=14" + "ts-jest": "^29.1.2", + "ts-node": "^10.9.2", + "typescript": "^5.3.3" } }, - "examples/sam/node_modules/@types/node": { - "version": "20.6.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.1.tgz", - "integrity": "sha512-4LcJvuXQlv4lTHnxwyHQZ3uR9Zw2j7m1C9DfuwoTFQQP4Pmu04O6IfLYgMmHoOCt0nosItLLZAH+sOrRE0Bo8g==", - "dev": true - }, "layers": { - "version": "1.14.0", + "version": "2.0.2", "license": "MIT-0", "dependencies": { - "aws-cdk": "^2.96.1", - "aws-cdk-lib": "^2.96.1", - "esbuild": "^0.19.3" + "aws-cdk": "^2.130.0", + "aws-cdk-lib": "^2.130.0", + "esbuild": "^0.20.1" }, "bin": { "layer": "bin/layers.js" @@ -210,9 +181,9 @@ } }, "node_modules/@aws-cdk/asset-awscli-v1": { - "version": "2.2.200", - "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.200.tgz", - "integrity": "sha512-Kf5J8DfJK4wZFWT2Myca0lhwke7LwHcHBo+4TvWOGJrFVVKVuuiLCkzPPRBQQVDj0Vtn2NBokZAz8pfMpAqAKg==" + "version": "2.2.202", + "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.202.tgz", + "integrity": "sha512-JqlF0D4+EVugnG5dAsNZMqhu3HW7ehOXm5SDMxMbXNDMdsF0pxtQKNHRl52z1U9igsHmaFpUgSGjbhAJ+0JONg==" }, "node_modules/@aws-cdk/asset-kubectl-v20": { "version": "2.1.2", @@ -225,9 +196,9 @@ "integrity": "sha512-DDt4SLdLOwWCjGtltH4VCST7hpOI5DzieuhGZsBpZ+AgJdSI2GCjklCXm0GCTwJG/SolkL5dtQXyUKgg9luBDg==" }, "node_modules/@aws-cdk/cli-lib-alpha": { - "version": "2.96.1-alpha.0", - "resolved": "https://registry.npmjs.org/@aws-cdk/cli-lib-alpha/-/cli-lib-alpha-2.96.1-alpha.0.tgz", - "integrity": "sha512-KRPG90986E+TbC9VDHR01R5SUct+aM5CEal8fLEn5hYg79Rp8Haaa96OwPaX/aiZdo+sM0v4fCaLICxG5/QZPg==", + "version": "2.121.1-alpha.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/cli-lib-alpha/-/cli-lib-alpha-2.121.1-alpha.0.tgz", + "integrity": "sha512-OG8VOukqFD4YFzmMN5+ppoVSvRugWaep7UVJle6JgvCN6/AvxTb2zCsAhhrCx4mDuckubD6WAkHNz2CRsFQAWg==", "engines": { "node": ">= 14.15.0" } @@ -360,50 +331,51 @@ "link": true }, "node_modules/@aws-sdk/client-appconfigdata": { - "version": "3.438.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-appconfigdata/-/client-appconfigdata-3.438.0.tgz", - "integrity": "sha512-1dYl/QqZaG7hMZ1dwUb68cNc3PpXIP/H2N3c4Kwqb0NPDbjoijSmuaEQIvdWaFjY7BZtvHD/9f8YmmXaQg2SlA==", + "version": "3.525.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-appconfigdata/-/client-appconfigdata-3.525.0.tgz", + "integrity": "sha512-GdtNOcTSzf5Gg4RxFskrVCNiyLi0KUMXjIueoDK1KdF7/aNCIAbIdqTaHZ4BwE9fma4JpKwexgCHX9myGeVinw==", "dev": true, "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.438.0", - "@aws-sdk/core": "3.436.0", - "@aws-sdk/credential-provider-node": "3.438.0", - "@aws-sdk/middleware-host-header": "3.433.0", - "@aws-sdk/middleware-logger": "3.433.0", - "@aws-sdk/middleware-recursion-detection": "3.433.0", - "@aws-sdk/middleware-signing": "3.433.0", - "@aws-sdk/middleware-user-agent": "3.438.0", - "@aws-sdk/region-config-resolver": "3.433.0", - "@aws-sdk/types": "3.433.0", - "@aws-sdk/util-endpoints": "3.438.0", - "@aws-sdk/util-user-agent-browser": "3.433.0", - "@aws-sdk/util-user-agent-node": "3.437.0", - "@smithy/config-resolver": "^2.0.16", - "@smithy/fetch-http-handler": "^2.2.4", - "@smithy/hash-node": "^2.0.12", - "@smithy/invalid-dependency": "^2.0.12", - "@smithy/middleware-content-length": "^2.0.14", - "@smithy/middleware-endpoint": "^2.1.3", - "@smithy/middleware-retry": "^2.0.18", - "@smithy/middleware-serde": "^2.0.12", - "@smithy/middleware-stack": "^2.0.6", - "@smithy/node-config-provider": "^2.1.3", - "@smithy/node-http-handler": "^2.1.8", - "@smithy/protocol-http": "^3.0.8", - "@smithy/smithy-client": "^2.1.12", - "@smithy/types": "^2.4.0", - "@smithy/url-parser": "^2.0.12", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.16", - "@smithy/util-defaults-mode-node": "^2.0.21", - "@smithy/util-endpoints": "^1.0.2", - "@smithy/util-retry": "^2.0.5", - "@smithy/util-stream": "^2.0.17", - "@smithy/util-utf8": "^2.0.0", + "@aws-sdk/client-sts": "3.525.0", + "@aws-sdk/core": "3.525.0", + "@aws-sdk/credential-provider-node": "3.525.0", + "@aws-sdk/middleware-host-header": "3.523.0", + "@aws-sdk/middleware-logger": "3.523.0", + "@aws-sdk/middleware-recursion-detection": "3.523.0", + "@aws-sdk/middleware-user-agent": "3.525.0", + "@aws-sdk/region-config-resolver": "3.525.0", + "@aws-sdk/types": "3.523.0", + "@aws-sdk/util-endpoints": "3.525.0", + "@aws-sdk/util-user-agent-browser": "3.523.0", + "@aws-sdk/util-user-agent-node": "3.525.0", + "@smithy/config-resolver": "^2.1.4", + "@smithy/core": "^1.3.5", + "@smithy/fetch-http-handler": "^2.4.3", + "@smithy/hash-node": "^2.1.3", + "@smithy/invalid-dependency": "^2.1.3", + "@smithy/middleware-content-length": "^2.1.3", + "@smithy/middleware-endpoint": "^2.4.4", + "@smithy/middleware-retry": "^2.1.4", + "@smithy/middleware-serde": "^2.1.3", + "@smithy/middleware-stack": "^2.1.3", + "@smithy/node-config-provider": "^2.2.4", + "@smithy/node-http-handler": "^2.4.1", + "@smithy/protocol-http": "^3.2.1", + "@smithy/smithy-client": "^2.4.2", + "@smithy/types": "^2.10.1", + "@smithy/url-parser": "^2.1.3", + "@smithy/util-base64": "^2.1.1", + "@smithy/util-body-length-browser": "^2.1.1", + "@smithy/util-body-length-node": "^2.2.1", + "@smithy/util-defaults-mode-browser": "^2.1.4", + "@smithy/util-defaults-mode-node": "^2.2.3", + "@smithy/util-endpoints": "^1.1.4", + "@smithy/util-middleware": "^2.1.3", + "@smithy/util-retry": "^2.1.3", + "@smithy/util-stream": "^2.1.3", + "@smithy/util-utf8": "^2.1.1", "tslib": "^2.5.0" }, "engines": { @@ -411,50 +383,52 @@ } }, "node_modules/@aws-sdk/client-cloudwatch": { - "version": "3.438.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch/-/client-cloudwatch-3.438.0.tgz", - "integrity": "sha512-hD45RojI2nJewAv5tTvlbVl9PjT06JkPn5k4z5/XkLEdsj2393MG3vhc6B64iwkOcLe5uJh7AhWbqNbAPAaXAA==", + "version": "3.525.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch/-/client-cloudwatch-3.525.0.tgz", + "integrity": "sha512-qi73IN/cGDxixHKnO99UIzGhYshStPXsZou8PNp0ee6ZJgyEpwtj1lFAoAEAbYcD0/PjtXsVNCOpyA1VXNjDDQ==", "dev": true, "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.438.0", - "@aws-sdk/core": "3.436.0", - "@aws-sdk/credential-provider-node": "3.438.0", - "@aws-sdk/middleware-host-header": "3.433.0", - "@aws-sdk/middleware-logger": "3.433.0", - "@aws-sdk/middleware-recursion-detection": "3.433.0", - "@aws-sdk/middleware-signing": "3.433.0", - "@aws-sdk/middleware-user-agent": "3.438.0", - "@aws-sdk/region-config-resolver": "3.433.0", - "@aws-sdk/types": "3.433.0", - "@aws-sdk/util-endpoints": "3.438.0", - "@aws-sdk/util-user-agent-browser": "3.433.0", - "@aws-sdk/util-user-agent-node": "3.437.0", - "@smithy/config-resolver": "^2.0.16", - "@smithy/fetch-http-handler": "^2.2.4", - "@smithy/hash-node": "^2.0.12", - "@smithy/invalid-dependency": "^2.0.12", - "@smithy/middleware-content-length": "^2.0.14", - "@smithy/middleware-endpoint": "^2.1.3", - "@smithy/middleware-retry": "^2.0.18", - "@smithy/middleware-serde": "^2.0.12", - "@smithy/middleware-stack": "^2.0.6", - "@smithy/node-config-provider": "^2.1.3", - "@smithy/node-http-handler": "^2.1.8", - "@smithy/protocol-http": "^3.0.8", - "@smithy/smithy-client": "^2.1.12", - "@smithy/types": "^2.4.0", - "@smithy/url-parser": "^2.0.12", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.16", - "@smithy/util-defaults-mode-node": "^2.0.21", - "@smithy/util-endpoints": "^1.0.2", - "@smithy/util-retry": "^2.0.5", - "@smithy/util-utf8": "^2.0.0", - "@smithy/util-waiter": "^2.0.12", + "@aws-sdk/client-sts": "3.525.0", + "@aws-sdk/core": "3.525.0", + "@aws-sdk/credential-provider-node": "3.525.0", + "@aws-sdk/middleware-host-header": "3.523.0", + "@aws-sdk/middleware-logger": "3.523.0", + "@aws-sdk/middleware-recursion-detection": "3.523.0", + "@aws-sdk/middleware-user-agent": "3.525.0", + "@aws-sdk/region-config-resolver": "3.525.0", + "@aws-sdk/types": "3.523.0", + "@aws-sdk/util-endpoints": "3.525.0", + "@aws-sdk/util-user-agent-browser": "3.523.0", + "@aws-sdk/util-user-agent-node": "3.525.0", + "@smithy/config-resolver": "^2.1.4", + "@smithy/core": "^1.3.5", + "@smithy/fetch-http-handler": "^2.4.3", + "@smithy/hash-node": "^2.1.3", + "@smithy/invalid-dependency": "^2.1.3", + "@smithy/middleware-compression": "^2.1.4", + "@smithy/middleware-content-length": "^2.1.3", + "@smithy/middleware-endpoint": "^2.4.4", + "@smithy/middleware-retry": "^2.1.4", + "@smithy/middleware-serde": "^2.1.3", + "@smithy/middleware-stack": "^2.1.3", + "@smithy/node-config-provider": "^2.2.4", + "@smithy/node-http-handler": "^2.4.1", + "@smithy/protocol-http": "^3.2.1", + "@smithy/smithy-client": "^2.4.2", + "@smithy/types": "^2.10.1", + "@smithy/url-parser": "^2.1.3", + "@smithy/util-base64": "^2.1.1", + "@smithy/util-body-length-browser": "^2.1.1", + "@smithy/util-body-length-node": "^2.2.1", + "@smithy/util-defaults-mode-browser": "^2.1.4", + "@smithy/util-defaults-mode-node": "^2.2.3", + "@smithy/util-endpoints": "^1.1.4", + "@smithy/util-middleware": "^2.1.3", + "@smithy/util-retry": "^2.1.3", + "@smithy/util-utf8": "^2.1.1", + "@smithy/util-waiter": "^2.1.3", "fast-xml-parser": "4.2.5", "tslib": "^2.5.0" }, @@ -463,105 +437,121 @@ } }, "node_modules/@aws-sdk/client-dynamodb": { - "version": "3.438.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.438.0.tgz", - "integrity": "sha512-LBKYjMezMRsxXP1BDnav/rUpwTOXrnD8OQKeYMbVfH0mmCDwd7Ac0cMyRM1c14sdm6Rr0gOCHIZ3Mjbup9r27Q==", + "version": "3.528.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.528.0.tgz", + "integrity": "sha512-qqgw2NM4m+WgZ5owLe7+ThtCpjnRxTA19ojFcxcrnKksXngwNqcWof6/OXhGkumeN73IdS08upiw4904ZbjZlQ==", + "dev": true, "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.438.0", - "@aws-sdk/core": "3.436.0", - "@aws-sdk/credential-provider-node": "3.438.0", - "@aws-sdk/middleware-endpoint-discovery": "3.433.0", - "@aws-sdk/middleware-host-header": "3.433.0", - "@aws-sdk/middleware-logger": "3.433.0", - "@aws-sdk/middleware-recursion-detection": "3.433.0", - "@aws-sdk/middleware-signing": "3.433.0", - "@aws-sdk/middleware-user-agent": "3.438.0", - "@aws-sdk/region-config-resolver": "3.433.0", - "@aws-sdk/types": "3.433.0", - "@aws-sdk/util-endpoints": "3.438.0", - "@aws-sdk/util-user-agent-browser": "3.433.0", - "@aws-sdk/util-user-agent-node": "3.437.0", - "@smithy/config-resolver": "^2.0.16", - "@smithy/fetch-http-handler": "^2.2.4", - "@smithy/hash-node": "^2.0.12", - "@smithy/invalid-dependency": "^2.0.12", - "@smithy/middleware-content-length": "^2.0.14", - "@smithy/middleware-endpoint": "^2.1.3", - "@smithy/middleware-retry": "^2.0.18", - "@smithy/middleware-serde": "^2.0.12", - "@smithy/middleware-stack": "^2.0.6", - "@smithy/node-config-provider": "^2.1.3", - "@smithy/node-http-handler": "^2.1.8", - "@smithy/protocol-http": "^3.0.8", - "@smithy/smithy-client": "^2.1.12", - "@smithy/types": "^2.4.0", - "@smithy/url-parser": "^2.0.12", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.16", - "@smithy/util-defaults-mode-node": "^2.0.21", - "@smithy/util-endpoints": "^1.0.2", - "@smithy/util-retry": "^2.0.5", - "@smithy/util-utf8": "^2.0.0", - "@smithy/util-waiter": "^2.0.12", + "@aws-sdk/client-sts": "3.525.0", + "@aws-sdk/core": "3.525.0", + "@aws-sdk/credential-provider-node": "3.525.0", + "@aws-sdk/middleware-endpoint-discovery": "3.525.0", + "@aws-sdk/middleware-host-header": "3.523.0", + "@aws-sdk/middleware-logger": "3.523.0", + "@aws-sdk/middleware-recursion-detection": "3.523.0", + "@aws-sdk/middleware-user-agent": "3.525.0", + "@aws-sdk/region-config-resolver": "3.525.0", + "@aws-sdk/types": "3.523.0", + "@aws-sdk/util-endpoints": "3.525.0", + "@aws-sdk/util-user-agent-browser": "3.523.0", + "@aws-sdk/util-user-agent-node": "3.525.0", + "@smithy/config-resolver": "^2.1.4", + "@smithy/core": "^1.3.5", + "@smithy/fetch-http-handler": "^2.4.3", + "@smithy/hash-node": "^2.1.3", + "@smithy/invalid-dependency": "^2.1.3", + "@smithy/middleware-content-length": "^2.1.3", + "@smithy/middleware-endpoint": "^2.4.4", + "@smithy/middleware-retry": "^2.1.4", + "@smithy/middleware-serde": "^2.1.3", + "@smithy/middleware-stack": "^2.1.3", + "@smithy/node-config-provider": "^2.2.4", + "@smithy/node-http-handler": "^2.4.1", + "@smithy/protocol-http": "^3.2.1", + "@smithy/smithy-client": "^2.4.2", + "@smithy/types": "^2.10.1", + "@smithy/url-parser": "^2.1.3", + "@smithy/util-base64": "^2.1.1", + "@smithy/util-body-length-browser": "^2.1.1", + "@smithy/util-body-length-node": "^2.2.1", + "@smithy/util-defaults-mode-browser": "^2.1.4", + "@smithy/util-defaults-mode-node": "^2.2.3", + "@smithy/util-endpoints": "^1.1.4", + "@smithy/util-middleware": "^2.1.3", + "@smithy/util-retry": "^2.1.3", + "@smithy/util-utf8": "^2.1.1", + "@smithy/util-waiter": "^2.1.3", "tslib": "^2.5.0", - "uuid": "^8.3.2" + "uuid": "^9.0.1" }, "engines": { "node": ">=14.0.0" } }, + "node_modules/@aws-sdk/client-dynamodb/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@aws-sdk/client-lambda": { - "version": "3.438.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.438.0.tgz", - "integrity": "sha512-FiWjoOabqJcJFHUJBZMzrL1IuvPNNrBnhVJknKo7SGiPtz8xeKZJ4VeJcClQjqGzuEbQCtqp/Ki5F7/EK3qv+w==", + "version": "3.525.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.525.0.tgz", + "integrity": "sha512-Jsz2F6X6DBV962T4wTyQgP2KqsIS3Hxw6shC5653tapCrR+AK2psFpeKs9w3SQA8D0SnEOAQf/5ay4n9sL+fZw==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.438.0", - "@aws-sdk/core": "3.436.0", - "@aws-sdk/credential-provider-node": "3.438.0", - "@aws-sdk/middleware-host-header": "3.433.0", - "@aws-sdk/middleware-logger": "3.433.0", - "@aws-sdk/middleware-recursion-detection": "3.433.0", - "@aws-sdk/middleware-signing": "3.433.0", - "@aws-sdk/middleware-user-agent": "3.438.0", - "@aws-sdk/region-config-resolver": "3.433.0", - "@aws-sdk/types": "3.433.0", - "@aws-sdk/util-endpoints": "3.438.0", - "@aws-sdk/util-user-agent-browser": "3.433.0", - "@aws-sdk/util-user-agent-node": "3.437.0", - "@smithy/config-resolver": "^2.0.16", - "@smithy/eventstream-serde-browser": "^2.0.12", - "@smithy/eventstream-serde-config-resolver": "^2.0.12", - "@smithy/eventstream-serde-node": "^2.0.12", - "@smithy/fetch-http-handler": "^2.2.4", - "@smithy/hash-node": "^2.0.12", - "@smithy/invalid-dependency": "^2.0.12", - "@smithy/middleware-content-length": "^2.0.14", - "@smithy/middleware-endpoint": "^2.1.3", - "@smithy/middleware-retry": "^2.0.18", - "@smithy/middleware-serde": "^2.0.12", - "@smithy/middleware-stack": "^2.0.6", - "@smithy/node-config-provider": "^2.1.3", - "@smithy/node-http-handler": "^2.1.8", - "@smithy/protocol-http": "^3.0.8", - "@smithy/smithy-client": "^2.1.12", - "@smithy/types": "^2.4.0", - "@smithy/url-parser": "^2.0.12", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.16", - "@smithy/util-defaults-mode-node": "^2.0.21", - "@smithy/util-endpoints": "^1.0.2", - "@smithy/util-retry": "^2.0.5", - "@smithy/util-stream": "^2.0.17", - "@smithy/util-utf8": "^2.0.0", - "@smithy/util-waiter": "^2.0.12", + "@aws-sdk/client-sts": "3.525.0", + "@aws-sdk/core": "3.525.0", + "@aws-sdk/credential-provider-node": "3.525.0", + "@aws-sdk/middleware-host-header": "3.523.0", + "@aws-sdk/middleware-logger": "3.523.0", + "@aws-sdk/middleware-recursion-detection": "3.523.0", + "@aws-sdk/middleware-user-agent": "3.525.0", + "@aws-sdk/region-config-resolver": "3.525.0", + "@aws-sdk/types": "3.523.0", + "@aws-sdk/util-endpoints": "3.525.0", + "@aws-sdk/util-user-agent-browser": "3.523.0", + "@aws-sdk/util-user-agent-node": "3.525.0", + "@smithy/config-resolver": "^2.1.4", + "@smithy/core": "^1.3.5", + "@smithy/eventstream-serde-browser": "^2.1.3", + "@smithy/eventstream-serde-config-resolver": "^2.1.3", + "@smithy/eventstream-serde-node": "^2.1.3", + "@smithy/fetch-http-handler": "^2.4.3", + "@smithy/hash-node": "^2.1.3", + "@smithy/invalid-dependency": "^2.1.3", + "@smithy/middleware-content-length": "^2.1.3", + "@smithy/middleware-endpoint": "^2.4.4", + "@smithy/middleware-retry": "^2.1.4", + "@smithy/middleware-serde": "^2.1.3", + "@smithy/middleware-stack": "^2.1.3", + "@smithy/node-config-provider": "^2.2.4", + "@smithy/node-http-handler": "^2.4.1", + "@smithy/protocol-http": "^3.2.1", + "@smithy/smithy-client": "^2.4.2", + "@smithy/types": "^2.10.1", + "@smithy/url-parser": "^2.1.3", + "@smithy/util-base64": "^2.1.1", + "@smithy/util-body-length-browser": "^2.1.1", + "@smithy/util-body-length-node": "^2.2.1", + "@smithy/util-defaults-mode-browser": "^2.1.4", + "@smithy/util-defaults-mode-node": "^2.2.3", + "@smithy/util-endpoints": "^1.1.4", + "@smithy/util-middleware": "^2.1.3", + "@smithy/util-retry": "^2.1.3", + "@smithy/util-stream": "^2.1.3", + "@smithy/util-utf8": "^2.1.1", + "@smithy/util-waiter": "^2.1.3", "tslib": "^2.5.0" }, "engines": { @@ -569,247 +559,333 @@ } }, "node_modules/@aws-sdk/client-secrets-manager": { - "version": "3.438.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.438.0.tgz", - "integrity": "sha512-l0c7l0gY181D3hULDPSZjE/OUfzuCSymFLkEwfBMgiB6jZAUcfmENr90rvOt4HS+QoHhDQvf8Fc+HL8A9NSVvw==", + "version": "3.525.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.525.0.tgz", + "integrity": "sha512-YhPfH87BWGNrkfV7VkP1EyjNzPkgqxen5aBqQKgJOxPy1M2+kNjqB9zQ/B/Q3T6cyQ/aduQ7Bi7bm3cqihmtbA==", "dev": true, "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.438.0", - "@aws-sdk/core": "3.436.0", - "@aws-sdk/credential-provider-node": "3.438.0", - "@aws-sdk/middleware-host-header": "3.433.0", - "@aws-sdk/middleware-logger": "3.433.0", - "@aws-sdk/middleware-recursion-detection": "3.433.0", - "@aws-sdk/middleware-signing": "3.433.0", - "@aws-sdk/middleware-user-agent": "3.438.0", - "@aws-sdk/region-config-resolver": "3.433.0", - "@aws-sdk/types": "3.433.0", - "@aws-sdk/util-endpoints": "3.438.0", - "@aws-sdk/util-user-agent-browser": "3.433.0", - "@aws-sdk/util-user-agent-node": "3.437.0", - "@smithy/config-resolver": "^2.0.16", - "@smithy/fetch-http-handler": "^2.2.4", - "@smithy/hash-node": "^2.0.12", - "@smithy/invalid-dependency": "^2.0.12", - "@smithy/middleware-content-length": "^2.0.14", - "@smithy/middleware-endpoint": "^2.1.3", - "@smithy/middleware-retry": "^2.0.18", - "@smithy/middleware-serde": "^2.0.12", - "@smithy/middleware-stack": "^2.0.6", - "@smithy/node-config-provider": "^2.1.3", - "@smithy/node-http-handler": "^2.1.8", - "@smithy/protocol-http": "^3.0.8", - "@smithy/smithy-client": "^2.1.12", - "@smithy/types": "^2.4.0", - "@smithy/url-parser": "^2.0.12", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.16", - "@smithy/util-defaults-mode-node": "^2.0.21", - "@smithy/util-endpoints": "^1.0.2", - "@smithy/util-retry": "^2.0.5", - "@smithy/util-utf8": "^2.0.0", + "@aws-sdk/client-sts": "3.525.0", + "@aws-sdk/core": "3.525.0", + "@aws-sdk/credential-provider-node": "3.525.0", + "@aws-sdk/middleware-host-header": "3.523.0", + "@aws-sdk/middleware-logger": "3.523.0", + "@aws-sdk/middleware-recursion-detection": "3.523.0", + "@aws-sdk/middleware-user-agent": "3.525.0", + "@aws-sdk/region-config-resolver": "3.525.0", + "@aws-sdk/types": "3.523.0", + "@aws-sdk/util-endpoints": "3.525.0", + "@aws-sdk/util-user-agent-browser": "3.523.0", + "@aws-sdk/util-user-agent-node": "3.525.0", + "@smithy/config-resolver": "^2.1.4", + "@smithy/core": "^1.3.5", + "@smithy/fetch-http-handler": "^2.4.3", + "@smithy/hash-node": "^2.1.3", + "@smithy/invalid-dependency": "^2.1.3", + "@smithy/middleware-content-length": "^2.1.3", + "@smithy/middleware-endpoint": "^2.4.4", + "@smithy/middleware-retry": "^2.1.4", + "@smithy/middleware-serde": "^2.1.3", + "@smithy/middleware-stack": "^2.1.3", + "@smithy/node-config-provider": "^2.2.4", + "@smithy/node-http-handler": "^2.4.1", + "@smithy/protocol-http": "^3.2.1", + "@smithy/smithy-client": "^2.4.2", + "@smithy/types": "^2.10.1", + "@smithy/url-parser": "^2.1.3", + "@smithy/util-base64": "^2.1.1", + "@smithy/util-body-length-browser": "^2.1.1", + "@smithy/util-body-length-node": "^2.2.1", + "@smithy/util-defaults-mode-browser": "^2.1.4", + "@smithy/util-defaults-mode-node": "^2.2.3", + "@smithy/util-endpoints": "^1.1.4", + "@smithy/util-middleware": "^2.1.3", + "@smithy/util-retry": "^2.1.3", + "@smithy/util-utf8": "^2.1.1", "tslib": "^2.5.0", - "uuid": "^8.3.2" + "uuid": "^9.0.1" }, "engines": { "node": ">=14.0.0" } }, + "node_modules/@aws-sdk/client-secrets-manager/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@aws-sdk/client-ssm": { - "version": "3.438.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-ssm/-/client-ssm-3.438.0.tgz", - "integrity": "sha512-ltu1YE5BWwhrdKukuLSJlZseCazTU1KCtNJDoXeUuqIKQmEiKZpTWRLOAHai280P90pmFbUdeV/jD3jXfRs+Eg==", + "version": "3.525.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-ssm/-/client-ssm-3.525.0.tgz", + "integrity": "sha512-q/z2CltlIePY/FGAFzuZpVRZuAzEopd2/YmQSCFtGZr04weKKXb+6qxdE3P3rdJf+a4MILcLszR3M+xmjK9Rlg==", + "dev": true, "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.438.0", - "@aws-sdk/core": "3.436.0", - "@aws-sdk/credential-provider-node": "3.438.0", - "@aws-sdk/middleware-host-header": "3.433.0", - "@aws-sdk/middleware-logger": "3.433.0", - "@aws-sdk/middleware-recursion-detection": "3.433.0", - "@aws-sdk/middleware-signing": "3.433.0", - "@aws-sdk/middleware-user-agent": "3.438.0", - "@aws-sdk/region-config-resolver": "3.433.0", - "@aws-sdk/types": "3.433.0", - "@aws-sdk/util-endpoints": "3.438.0", - "@aws-sdk/util-user-agent-browser": "3.433.0", - "@aws-sdk/util-user-agent-node": "3.437.0", - "@smithy/config-resolver": "^2.0.16", - "@smithy/fetch-http-handler": "^2.2.4", - "@smithy/hash-node": "^2.0.12", - "@smithy/invalid-dependency": "^2.0.12", - "@smithy/middleware-content-length": "^2.0.14", - "@smithy/middleware-endpoint": "^2.1.3", - "@smithy/middleware-retry": "^2.0.18", - "@smithy/middleware-serde": "^2.0.12", - "@smithy/middleware-stack": "^2.0.6", - "@smithy/node-config-provider": "^2.1.3", - "@smithy/node-http-handler": "^2.1.8", - "@smithy/protocol-http": "^3.0.8", - "@smithy/smithy-client": "^2.1.12", - "@smithy/types": "^2.4.0", - "@smithy/url-parser": "^2.0.12", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.16", - "@smithy/util-defaults-mode-node": "^2.0.21", - "@smithy/util-endpoints": "^1.0.2", - "@smithy/util-retry": "^2.0.5", - "@smithy/util-utf8": "^2.0.0", - "@smithy/util-waiter": "^2.0.12", + "@aws-sdk/client-sts": "3.525.0", + "@aws-sdk/core": "3.525.0", + "@aws-sdk/credential-provider-node": "3.525.0", + "@aws-sdk/middleware-host-header": "3.523.0", + "@aws-sdk/middleware-logger": "3.523.0", + "@aws-sdk/middleware-recursion-detection": "3.523.0", + "@aws-sdk/middleware-user-agent": "3.525.0", + "@aws-sdk/region-config-resolver": "3.525.0", + "@aws-sdk/types": "3.523.0", + "@aws-sdk/util-endpoints": "3.525.0", + "@aws-sdk/util-user-agent-browser": "3.523.0", + "@aws-sdk/util-user-agent-node": "3.525.0", + "@smithy/config-resolver": "^2.1.4", + "@smithy/core": "^1.3.5", + "@smithy/fetch-http-handler": "^2.4.3", + "@smithy/hash-node": "^2.1.3", + "@smithy/invalid-dependency": "^2.1.3", + "@smithy/middleware-content-length": "^2.1.3", + "@smithy/middleware-endpoint": "^2.4.4", + "@smithy/middleware-retry": "^2.1.4", + "@smithy/middleware-serde": "^2.1.3", + "@smithy/middleware-stack": "^2.1.3", + "@smithy/node-config-provider": "^2.2.4", + "@smithy/node-http-handler": "^2.4.1", + "@smithy/protocol-http": "^3.2.1", + "@smithy/smithy-client": "^2.4.2", + "@smithy/types": "^2.10.1", + "@smithy/url-parser": "^2.1.3", + "@smithy/util-base64": "^2.1.1", + "@smithy/util-body-length-browser": "^2.1.1", + "@smithy/util-body-length-node": "^2.2.1", + "@smithy/util-defaults-mode-browser": "^2.1.4", + "@smithy/util-defaults-mode-node": "^2.2.3", + "@smithy/util-endpoints": "^1.1.4", + "@smithy/util-middleware": "^2.1.3", + "@smithy/util-retry": "^2.1.3", + "@smithy/util-utf8": "^2.1.1", + "@smithy/util-waiter": "^2.1.3", "tslib": "^2.5.0", - "uuid": "^8.3.2" + "uuid": "^9.0.1" }, "engines": { "node": ">=14.0.0" } }, + "node_modules/@aws-sdk/client-ssm/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@aws-sdk/client-sso": { - "version": "3.438.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.438.0.tgz", - "integrity": "sha512-L/xKq+K78PShLku8x5gM6lZDUp7LhFJ2ksKH7Vll+exSZq+QUaxuzjp4gqdzh6B0oIshv2jssQlUa0ScOmVRMg==", + "version": "3.525.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.525.0.tgz", + "integrity": "sha512-6KwGQWFoNLH1UupdWPFdKPfTgjSz1kN8/r8aCzuvvXBe4Pz+iDUZ6FEJzGWNc9AapjvZDNO1hs23slomM9rTaA==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/core": "3.525.0", + "@aws-sdk/middleware-host-header": "3.523.0", + "@aws-sdk/middleware-logger": "3.523.0", + "@aws-sdk/middleware-recursion-detection": "3.523.0", + "@aws-sdk/middleware-user-agent": "3.525.0", + "@aws-sdk/region-config-resolver": "3.525.0", + "@aws-sdk/types": "3.523.0", + "@aws-sdk/util-endpoints": "3.525.0", + "@aws-sdk/util-user-agent-browser": "3.523.0", + "@aws-sdk/util-user-agent-node": "3.525.0", + "@smithy/config-resolver": "^2.1.4", + "@smithy/core": "^1.3.5", + "@smithy/fetch-http-handler": "^2.4.3", + "@smithy/hash-node": "^2.1.3", + "@smithy/invalid-dependency": "^2.1.3", + "@smithy/middleware-content-length": "^2.1.3", + "@smithy/middleware-endpoint": "^2.4.4", + "@smithy/middleware-retry": "^2.1.4", + "@smithy/middleware-serde": "^2.1.3", + "@smithy/middleware-stack": "^2.1.3", + "@smithy/node-config-provider": "^2.2.4", + "@smithy/node-http-handler": "^2.4.1", + "@smithy/protocol-http": "^3.2.1", + "@smithy/smithy-client": "^2.4.2", + "@smithy/types": "^2.10.1", + "@smithy/url-parser": "^2.1.3", + "@smithy/util-base64": "^2.1.1", + "@smithy/util-body-length-browser": "^2.1.1", + "@smithy/util-body-length-node": "^2.2.1", + "@smithy/util-defaults-mode-browser": "^2.1.4", + "@smithy/util-defaults-mode-node": "^2.2.3", + "@smithy/util-endpoints": "^1.1.4", + "@smithy/util-middleware": "^2.1.3", + "@smithy/util-retry": "^2.1.3", + "@smithy/util-utf8": "^2.1.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sso-oidc": { + "version": "3.525.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.525.0.tgz", + "integrity": "sha512-zz13k/6RkjPSLmReSeGxd8wzGiiZa4Odr2Tv3wTcxClM4wOjD+zOgGv4Fe32b9AMqaueiCdjbvdu7AKcYxFA4A==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/core": "3.436.0", - "@aws-sdk/middleware-host-header": "3.433.0", - "@aws-sdk/middleware-logger": "3.433.0", - "@aws-sdk/middleware-recursion-detection": "3.433.0", - "@aws-sdk/middleware-user-agent": "3.438.0", - "@aws-sdk/region-config-resolver": "3.433.0", - "@aws-sdk/types": "3.433.0", - "@aws-sdk/util-endpoints": "3.438.0", - "@aws-sdk/util-user-agent-browser": "3.433.0", - "@aws-sdk/util-user-agent-node": "3.437.0", - "@smithy/config-resolver": "^2.0.16", - "@smithy/fetch-http-handler": "^2.2.4", - "@smithy/hash-node": "^2.0.12", - "@smithy/invalid-dependency": "^2.0.12", - "@smithy/middleware-content-length": "^2.0.14", - "@smithy/middleware-endpoint": "^2.1.3", - "@smithy/middleware-retry": "^2.0.18", - "@smithy/middleware-serde": "^2.0.12", - "@smithy/middleware-stack": "^2.0.6", - "@smithy/node-config-provider": "^2.1.3", - "@smithy/node-http-handler": "^2.1.8", - "@smithy/protocol-http": "^3.0.8", - "@smithy/smithy-client": "^2.1.12", - "@smithy/types": "^2.4.0", - "@smithy/url-parser": "^2.0.12", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.16", - "@smithy/util-defaults-mode-node": "^2.0.21", - "@smithy/util-endpoints": "^1.0.2", - "@smithy/util-retry": "^2.0.5", - "@smithy/util-utf8": "^2.0.0", + "@aws-sdk/client-sts": "3.525.0", + "@aws-sdk/core": "3.525.0", + "@aws-sdk/middleware-host-header": "3.523.0", + "@aws-sdk/middleware-logger": "3.523.0", + "@aws-sdk/middleware-recursion-detection": "3.523.0", + "@aws-sdk/middleware-user-agent": "3.525.0", + "@aws-sdk/region-config-resolver": "3.525.0", + "@aws-sdk/types": "3.523.0", + "@aws-sdk/util-endpoints": "3.525.0", + "@aws-sdk/util-user-agent-browser": "3.523.0", + "@aws-sdk/util-user-agent-node": "3.525.0", + "@smithy/config-resolver": "^2.1.4", + "@smithy/core": "^1.3.5", + "@smithy/fetch-http-handler": "^2.4.3", + "@smithy/hash-node": "^2.1.3", + "@smithy/invalid-dependency": "^2.1.3", + "@smithy/middleware-content-length": "^2.1.3", + "@smithy/middleware-endpoint": "^2.4.4", + "@smithy/middleware-retry": "^2.1.4", + "@smithy/middleware-serde": "^2.1.3", + "@smithy/middleware-stack": "^2.1.3", + "@smithy/node-config-provider": "^2.2.4", + "@smithy/node-http-handler": "^2.4.1", + "@smithy/protocol-http": "^3.2.1", + "@smithy/smithy-client": "^2.4.2", + "@smithy/types": "^2.10.1", + "@smithy/url-parser": "^2.1.3", + "@smithy/util-base64": "^2.1.1", + "@smithy/util-body-length-browser": "^2.1.1", + "@smithy/util-body-length-node": "^2.2.1", + "@smithy/util-defaults-mode-browser": "^2.1.4", + "@smithy/util-defaults-mode-node": "^2.2.3", + "@smithy/util-endpoints": "^1.1.4", + "@smithy/util-middleware": "^2.1.3", + "@smithy/util-retry": "^2.1.3", + "@smithy/util-utf8": "^2.1.1", "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" + }, + "peerDependencies": { + "@aws-sdk/credential-provider-node": "^3.525.0" } }, "node_modules/@aws-sdk/client-sts": { - "version": "3.438.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.438.0.tgz", - "integrity": "sha512-UBxLZKVVvbR4LHwSNSqaKx22YBSOGkavrh4SyDP8o8XOlXeRxTCllfSfjL9K5Mktp+ZwQ2NiubNcwmvUcGKbbg==", + "version": "3.525.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.525.0.tgz", + "integrity": "sha512-a8NUGRvO6rkfTZCbMaCsjDjLbERCwIUU9dIywFYcRgbFhkupJ7fSaZz3Het98U51M9ZbTEpaTa3fz0HaJv8VJw==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/core": "3.436.0", - "@aws-sdk/credential-provider-node": "3.438.0", - "@aws-sdk/middleware-host-header": "3.433.0", - "@aws-sdk/middleware-logger": "3.433.0", - "@aws-sdk/middleware-recursion-detection": "3.433.0", - "@aws-sdk/middleware-sdk-sts": "3.433.0", - "@aws-sdk/middleware-signing": "3.433.0", - "@aws-sdk/middleware-user-agent": "3.438.0", - "@aws-sdk/region-config-resolver": "3.433.0", - "@aws-sdk/types": "3.433.0", - "@aws-sdk/util-endpoints": "3.438.0", - "@aws-sdk/util-user-agent-browser": "3.433.0", - "@aws-sdk/util-user-agent-node": "3.437.0", - "@smithy/config-resolver": "^2.0.16", - "@smithy/fetch-http-handler": "^2.2.4", - "@smithy/hash-node": "^2.0.12", - "@smithy/invalid-dependency": "^2.0.12", - "@smithy/middleware-content-length": "^2.0.14", - "@smithy/middleware-endpoint": "^2.1.3", - "@smithy/middleware-retry": "^2.0.18", - "@smithy/middleware-serde": "^2.0.12", - "@smithy/middleware-stack": "^2.0.6", - "@smithy/node-config-provider": "^2.1.3", - "@smithy/node-http-handler": "^2.1.8", - "@smithy/protocol-http": "^3.0.8", - "@smithy/smithy-client": "^2.1.12", - "@smithy/types": "^2.4.0", - "@smithy/url-parser": "^2.0.12", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.16", - "@smithy/util-defaults-mode-node": "^2.0.21", - "@smithy/util-endpoints": "^1.0.2", - "@smithy/util-retry": "^2.0.5", - "@smithy/util-utf8": "^2.0.0", + "@aws-sdk/core": "3.525.0", + "@aws-sdk/middleware-host-header": "3.523.0", + "@aws-sdk/middleware-logger": "3.523.0", + "@aws-sdk/middleware-recursion-detection": "3.523.0", + "@aws-sdk/middleware-user-agent": "3.525.0", + "@aws-sdk/region-config-resolver": "3.525.0", + "@aws-sdk/types": "3.523.0", + "@aws-sdk/util-endpoints": "3.525.0", + "@aws-sdk/util-user-agent-browser": "3.523.0", + "@aws-sdk/util-user-agent-node": "3.525.0", + "@smithy/config-resolver": "^2.1.4", + "@smithy/core": "^1.3.5", + "@smithy/fetch-http-handler": "^2.4.3", + "@smithy/hash-node": "^2.1.3", + "@smithy/invalid-dependency": "^2.1.3", + "@smithy/middleware-content-length": "^2.1.3", + "@smithy/middleware-endpoint": "^2.4.4", + "@smithy/middleware-retry": "^2.1.4", + "@smithy/middleware-serde": "^2.1.3", + "@smithy/middleware-stack": "^2.1.3", + "@smithy/node-config-provider": "^2.2.4", + "@smithy/node-http-handler": "^2.4.1", + "@smithy/protocol-http": "^3.2.1", + "@smithy/smithy-client": "^2.4.2", + "@smithy/types": "^2.10.1", + "@smithy/url-parser": "^2.1.3", + "@smithy/util-base64": "^2.1.1", + "@smithy/util-body-length-browser": "^2.1.1", + "@smithy/util-body-length-node": "^2.2.1", + "@smithy/util-defaults-mode-browser": "^2.1.4", + "@smithy/util-defaults-mode-node": "^2.2.3", + "@smithy/util-endpoints": "^1.1.4", + "@smithy/util-middleware": "^2.1.3", + "@smithy/util-retry": "^2.1.3", + "@smithy/util-utf8": "^2.1.1", "fast-xml-parser": "4.2.5", "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" + }, + "peerDependencies": { + "@aws-sdk/credential-provider-node": "^3.525.0" } }, "node_modules/@aws-sdk/client-xray": { - "version": "3.438.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-xray/-/client-xray-3.438.0.tgz", - "integrity": "sha512-tNkGnVFZdKaFGWpGOWy8N9bUH9T7FarmW1Wlnnjkk8uyBYR/0wOs+ICFTEpz+orOluQ3egQdF352CJyM5MY+VQ==", + "version": "3.525.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-xray/-/client-xray-3.525.0.tgz", + "integrity": "sha512-A09mMsmi6oC0i+AW41hmxsIGZreN79js7g3rEgZU05kFC8UAnxhZ7fX1GUoMV9B1ww17r2eY9zS/45aEcEckNw==", "dev": true, "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.438.0", - "@aws-sdk/core": "3.436.0", - "@aws-sdk/credential-provider-node": "3.438.0", - "@aws-sdk/middleware-host-header": "3.433.0", - "@aws-sdk/middleware-logger": "3.433.0", - "@aws-sdk/middleware-recursion-detection": "3.433.0", - "@aws-sdk/middleware-signing": "3.433.0", - "@aws-sdk/middleware-user-agent": "3.438.0", - "@aws-sdk/region-config-resolver": "3.433.0", - "@aws-sdk/types": "3.433.0", - "@aws-sdk/util-endpoints": "3.438.0", - "@aws-sdk/util-user-agent-browser": "3.433.0", - "@aws-sdk/util-user-agent-node": "3.437.0", - "@smithy/config-resolver": "^2.0.16", - "@smithy/fetch-http-handler": "^2.2.4", - "@smithy/hash-node": "^2.0.12", - "@smithy/invalid-dependency": "^2.0.12", - "@smithy/middleware-content-length": "^2.0.14", - "@smithy/middleware-endpoint": "^2.1.3", - "@smithy/middleware-retry": "^2.0.18", - "@smithy/middleware-serde": "^2.0.12", - "@smithy/middleware-stack": "^2.0.6", - "@smithy/node-config-provider": "^2.1.3", - "@smithy/node-http-handler": "^2.1.8", - "@smithy/protocol-http": "^3.0.8", - "@smithy/smithy-client": "^2.1.12", - "@smithy/types": "^2.4.0", - "@smithy/url-parser": "^2.0.12", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.16", - "@smithy/util-defaults-mode-node": "^2.0.21", - "@smithy/util-endpoints": "^1.0.2", - "@smithy/util-retry": "^2.0.5", - "@smithy/util-utf8": "^2.0.0", + "@aws-sdk/client-sts": "3.525.0", + "@aws-sdk/core": "3.525.0", + "@aws-sdk/credential-provider-node": "3.525.0", + "@aws-sdk/middleware-host-header": "3.523.0", + "@aws-sdk/middleware-logger": "3.523.0", + "@aws-sdk/middleware-recursion-detection": "3.523.0", + "@aws-sdk/middleware-user-agent": "3.525.0", + "@aws-sdk/region-config-resolver": "3.525.0", + "@aws-sdk/types": "3.523.0", + "@aws-sdk/util-endpoints": "3.525.0", + "@aws-sdk/util-user-agent-browser": "3.523.0", + "@aws-sdk/util-user-agent-node": "3.525.0", + "@smithy/config-resolver": "^2.1.4", + "@smithy/core": "^1.3.5", + "@smithy/fetch-http-handler": "^2.4.3", + "@smithy/hash-node": "^2.1.3", + "@smithy/invalid-dependency": "^2.1.3", + "@smithy/middleware-content-length": "^2.1.3", + "@smithy/middleware-endpoint": "^2.4.4", + "@smithy/middleware-retry": "^2.1.4", + "@smithy/middleware-serde": "^2.1.3", + "@smithy/middleware-stack": "^2.1.3", + "@smithy/node-config-provider": "^2.2.4", + "@smithy/node-http-handler": "^2.4.1", + "@smithy/protocol-http": "^3.2.1", + "@smithy/smithy-client": "^2.4.2", + "@smithy/types": "^2.10.1", + "@smithy/url-parser": "^2.1.3", + "@smithy/util-base64": "^2.1.1", + "@smithy/util-body-length-browser": "^2.1.1", + "@smithy/util-body-length-node": "^2.2.1", + "@smithy/util-defaults-mode-browser": "^2.1.4", + "@smithy/util-defaults-mode-node": "^2.2.3", + "@smithy/util-endpoints": "^1.1.4", + "@smithy/util-middleware": "^2.1.3", + "@smithy/util-retry": "^2.1.3", + "@smithy/util-utf8": "^2.1.1", "tslib": "^2.5.0" }, "engines": { @@ -817,24 +893,48 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.436.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.436.0.tgz", - "integrity": "sha512-vX5/LjXvCejC2XUY6TSg1oozjqK6BvkE75t0ys9dgqyr5PlZyZksMoeAFHUlj0sCjhT3ziWCujP1oiSpPWY9hg==", - "dependencies": { - "@smithy/smithy-client": "^2.1.12" + "version": "3.525.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.525.0.tgz", + "integrity": "sha512-E3LtEtMWCriQOFZpVKpLYzbdw/v2PAOEAMhn2VRRZ1g0/g1TXzQrfhEU2yd8l/vQEJaCJ82ooGGg7YECviBUxA==", + "dependencies": { + "@smithy/core": "^1.3.5", + "@smithy/protocol-http": "^3.2.1", + "@smithy/signature-v4": "^2.1.3", + "@smithy/smithy-client": "^2.4.2", + "@smithy/types": "^2.10.1", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.433.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.433.0.tgz", - "integrity": "sha512-Vl7Qz5qYyxBurMn6hfSiNJeUHSqfVUlMt0C1Bds3tCkl3IzecRWwyBOlxtxO3VCrgVeW3HqswLzCvhAFzPH6nQ==", + "version": "3.523.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.523.0.tgz", + "integrity": "sha512-Y6DWdH6/OuMDoNKVzZlNeBc6f1Yjk1lYMjANKpIhMbkRCvLJw/PYZKOZa8WpXbTYdgg9XLjKybnLIb3ww3uuzA==", + "dependencies": { + "@aws-sdk/types": "3.523.0", + "@smithy/property-provider": "^2.1.3", + "@smithy/types": "^2.10.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.525.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.525.0.tgz", + "integrity": "sha512-RNWQGuSBQZhl3iqklOslUEfQ4br1V3DCPboMpeqFtddUWJV3m2u2extFur9/4Uy+1EHVF120IwZUKtd8dF+ibw==", "dependencies": { - "@aws-sdk/types": "3.433.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.4.0", + "@aws-sdk/types": "3.523.0", + "@smithy/fetch-http-handler": "^2.4.3", + "@smithy/node-http-handler": "^2.4.1", + "@smithy/property-provider": "^2.1.3", + "@smithy/protocol-http": "^3.2.1", + "@smithy/smithy-client": "^2.4.2", + "@smithy/types": "^2.10.1", + "@smithy/util-stream": "^2.1.3", "tslib": "^2.5.0" }, "engines": { @@ -842,19 +942,20 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.438.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.438.0.tgz", - "integrity": "sha512-WYPQR3pXoHJjn9/RMWipUhsUNFy6zhOiII6u8LJ5w84aNqIjV4+BdRYztRNGJD98jdtekhbkX0YKoSuZqP+unQ==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.433.0", - "@aws-sdk/credential-provider-process": "3.433.0", - "@aws-sdk/credential-provider-sso": "3.438.0", - "@aws-sdk/credential-provider-web-identity": "3.433.0", - "@aws-sdk/types": "3.433.0", - "@smithy/credential-provider-imds": "^2.0.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.4.0", + "version": "3.525.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.525.0.tgz", + "integrity": "sha512-JDnccfK5JRb9jcgpc9lirL9PyCwGIqY0nKdw3LlX5WL5vTpTG4E1q7rLAlpNh7/tFD1n66Itarfv2tsyHMIqCw==", + "dependencies": { + "@aws-sdk/client-sts": "3.525.0", + "@aws-sdk/credential-provider-env": "3.523.0", + "@aws-sdk/credential-provider-process": "3.523.0", + "@aws-sdk/credential-provider-sso": "3.525.0", + "@aws-sdk/credential-provider-web-identity": "3.525.0", + "@aws-sdk/types": "3.523.0", + "@smithy/credential-provider-imds": "^2.2.3", + "@smithy/property-provider": "^2.1.3", + "@smithy/shared-ini-file-loader": "^2.3.3", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -862,20 +963,21 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.438.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.438.0.tgz", - "integrity": "sha512-uaw3D2R0svyrC32qyZ2aOv/l0AT9eClh+eQsZJTQD3Kz9q+2VdeOBThQ8fsMfRtm26nUbZo6A/CRwxkm6okI+w==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.433.0", - "@aws-sdk/credential-provider-ini": "3.438.0", - "@aws-sdk/credential-provider-process": "3.433.0", - "@aws-sdk/credential-provider-sso": "3.438.0", - "@aws-sdk/credential-provider-web-identity": "3.433.0", - "@aws-sdk/types": "3.433.0", - "@smithy/credential-provider-imds": "^2.0.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.4.0", + "version": "3.525.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.525.0.tgz", + "integrity": "sha512-RJXlO8goGXpnoHQAyrCcJ0QtWEOFa34LSbfdqBIjQX/fwnjUuEmiGdXTV3AZmwYQ7juk49tfBneHbtOP3AGqsQ==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.523.0", + "@aws-sdk/credential-provider-http": "3.525.0", + "@aws-sdk/credential-provider-ini": "3.525.0", + "@aws-sdk/credential-provider-process": "3.523.0", + "@aws-sdk/credential-provider-sso": "3.525.0", + "@aws-sdk/credential-provider-web-identity": "3.525.0", + "@aws-sdk/types": "3.523.0", + "@smithy/credential-provider-imds": "^2.2.3", + "@smithy/property-provider": "^2.1.3", + "@smithy/shared-ini-file-loader": "^2.3.3", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -883,14 +985,14 @@ } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.433.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.433.0.tgz", - "integrity": "sha512-W7FcGlQjio9Y/PepcZGRyl5Bpwb0uWU7qIUCh+u4+q2mW4D5ZngXg8V/opL9/I/p4tUH9VXZLyLGwyBSkdhL+A==", - "dependencies": { - "@aws-sdk/types": "3.433.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.4.0", + "version": "3.523.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.523.0.tgz", + "integrity": "sha512-f0LP9KlFmMvPWdKeUKYlZ6FkQAECUeZMmISsv6NKtvPCI9e4O4cLTeR09telwDK8P0HrgcRuZfXM7E30m8re0Q==", + "dependencies": { + "@aws-sdk/types": "3.523.0", + "@smithy/property-provider": "^2.1.3", + "@smithy/shared-ini-file-loader": "^2.3.3", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -898,16 +1000,16 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.438.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.438.0.tgz", - "integrity": "sha512-Xykli/64xR18cBV5P0XFxcH120omtfAjC/cFy/9nFU/+dPvbk0uu1yEOZYteWHyGGkPN4PkHmbh60GiUCLQkWQ==", - "dependencies": { - "@aws-sdk/client-sso": "3.438.0", - "@aws-sdk/token-providers": "3.438.0", - "@aws-sdk/types": "3.433.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.4.0", + "version": "3.525.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.525.0.tgz", + "integrity": "sha512-7V7ybtufxdD3plxeIeB6aqHZeFIUlAyPphXIUgXrGY10iNcosL970rQPBeggsohe4gCM6UvY2TfMeEcr+ZE8FA==", + "dependencies": { + "@aws-sdk/client-sso": "3.525.0", + "@aws-sdk/token-providers": "3.525.0", + "@aws-sdk/types": "3.523.0", + "@smithy/property-provider": "^2.1.3", + "@smithy/shared-ini-file-loader": "^2.3.3", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -915,13 +1017,14 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.433.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.433.0.tgz", - "integrity": "sha512-RlwjP1I5wO+aPpwyCp23Mk8nmRbRL33hqRASy73c4JA2z2YiRua+ryt6MalIxehhwQU6xvXUKulJnPG9VaMFZg==", - "dependencies": { - "@aws-sdk/types": "3.433.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.4.0", + "version": "3.525.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.525.0.tgz", + "integrity": "sha512-sAukOjR1oKb2JXG4nPpuBFpSwGUhrrY17PG/xbTy8NAoLLhrqRwnErcLfdTfmj6tH+3094k6ws/Sh8a35ae7fA==", + "dependencies": { + "@aws-sdk/client-sts": "3.525.0", + "@aws-sdk/types": "3.523.0", + "@smithy/property-provider": "^2.1.3", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -929,9 +1032,10 @@ } }, "node_modules/@aws-sdk/endpoint-cache": { - "version": "3.310.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.310.0.tgz", - "integrity": "sha512-y3wipforet41EDTI0vnzxILqwAGll1KfI5qcdX9pXF/WF1f+3frcOtPiWtQEZQpy4czRogKm3BHo70QBYAZxlQ==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.495.0.tgz", + "integrity": "sha512-XCDrpiS50WaPzPzp7FwsChPHtX9PQQUU4nRzcn2N7IkUtpcFCUx8m1PAZe086VQr6hrbdeE4Z4j8hUPNwVdJGQ==", + "dev": true, "dependencies": { "mnemonist": "0.38.3", "tslib": "^2.5.0" @@ -952,11 +1056,14 @@ } }, "node_modules/@aws-sdk/lib-dynamodb": { - "version": "3.438.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.438.0.tgz", - "integrity": "sha512-LJXfLabOLytVLBWHVdiPHZCR8RSNCLzaadyLovVXrAPe+c2mbpyUJ+ojO0fB1AlVJnfxcDZLskzUYSP4sw0v5w==", + "version": "3.528.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-dynamodb/-/lib-dynamodb-3.528.0.tgz", + "integrity": "sha512-BGyST10K2jRE8m+EuW8SVIMjsDd5/KkNhCv8Qm8dUsgSwSWSOokG0B0adOJBg5702X5j6N5mNi47Qd6mEViySA==", + "dev": true, "dependencies": { - "@aws-sdk/util-dynamodb": "3.438.0", + "@aws-sdk/util-dynamodb": "3.528.0", + "@smithy/smithy-client": "^2.4.2", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -967,15 +1074,16 @@ } }, "node_modules/@aws-sdk/middleware-endpoint-discovery": { - "version": "3.433.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.433.0.tgz", - "integrity": "sha512-eGQcncEtnQs2wMpLkJoreba/5547/eDDojGLuGjBmKtbZbVNZ9nbyCC//WIsmgT5CR5Bg9D+bNSsijmYpU6Qpg==", - "dependencies": { - "@aws-sdk/endpoint-cache": "3.310.0", - "@aws-sdk/types": "3.433.0", - "@smithy/node-config-provider": "^2.1.3", - "@smithy/protocol-http": "^3.0.8", - "@smithy/types": "^2.4.0", + "version": "3.525.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.525.0.tgz", + "integrity": "sha512-nT/XYP3RDRWPFCTEOZQbOC3HWmUkxB0fDuobmH8WzL92MCBGz9gBG/q9XBxiw9pHk9Dky/MIkLV50BlGB3kM7g==", + "dev": true, + "dependencies": { + "@aws-sdk/endpoint-cache": "3.495.0", + "@aws-sdk/types": "3.523.0", + "@smithy/node-config-provider": "^2.2.4", + "@smithy/protocol-http": "^3.2.1", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -983,13 +1091,13 @@ } }, "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.433.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.433.0.tgz", - "integrity": "sha512-mBTq3UWv1UzeHG+OfUQ2MB/5GEkt5LTKFaUqzL7ESwzW8XtpBgXnjZvIwu3Vcd3sEetMwijwaGiJhY0ae/YyaA==", + "version": "3.523.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.523.0.tgz", + "integrity": "sha512-4g3q7Ta9sdD9TMUuohBAkbx/e3I/juTqfKi7TPgP+8jxcYX72MOsgemAMHuP6CX27eyj4dpvjH+w4SIVDiDSmg==", "dependencies": { - "@aws-sdk/types": "3.433.0", - "@smithy/protocol-http": "^3.0.8", - "@smithy/types": "^2.4.0", + "@aws-sdk/types": "3.523.0", + "@smithy/protocol-http": "^3.2.1", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -997,12 +1105,12 @@ } }, "node_modules/@aws-sdk/middleware-logger": { - "version": "3.433.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.433.0.tgz", - "integrity": "sha512-We346Fb5xGonTGVZC9Nvqtnqy74VJzYuTLLiuuftA5sbNzftBDy/22QCfvYSTOAl3bvif+dkDUzQY2ihc5PwOQ==", + "version": "3.523.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.523.0.tgz", + "integrity": "sha512-PeDNJNhfiaZx54LBaLTXzUaJ9LXFwDFFIksipjqjvxMafnoVcQwKbkoPUWLe5ytT4nnL1LogD3s55mERFUsnwg==", "dependencies": { - "@aws-sdk/types": "3.433.0", - "@smithy/types": "^2.4.0", + "@aws-sdk/types": "3.523.0", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -1010,44 +1118,13 @@ } }, "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.433.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.433.0.tgz", - "integrity": "sha512-HEvYC9PQlWY/ccUYtLvAlwwf1iCif2TSAmLNr3YTBRVa98x6jKL0hlCrHWYklFeqOGSKy6XhE+NGJMUII0/HaQ==", - "dependencies": { - "@aws-sdk/types": "3.433.0", - "@smithy/protocol-http": "^3.0.8", - "@smithy/types": "^2.4.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-sdk-sts": { - "version": "3.433.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.433.0.tgz", - "integrity": "sha512-ORYbJnBejUyonFl5FwIqhvI3Cq6sAp9j+JpkKZtFNma9tFPdrhmYgfCeNH32H/wGTQV/tUoQ3luh0gA4cuk6DA==", - "dependencies": { - "@aws-sdk/middleware-signing": "3.433.0", - "@aws-sdk/types": "3.433.0", - "@smithy/types": "^2.4.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-signing": { - "version": "3.433.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.433.0.tgz", - "integrity": "sha512-jxPvt59NZo/epMNLNTu47ikmP8v0q217I6bQFGJG7JVFnfl36zDktMwGw+0xZR80qiK47/2BWrNpta61Zd2FxQ==", + "version": "3.523.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.523.0.tgz", + "integrity": "sha512-nZ3Vt7ehfSDYnrcg/aAfjjvpdE+61B3Zk68i6/hSUIegT3IH9H1vSW67NDKVp+50hcEfzWwM2HMPXxlzuyFyrw==", "dependencies": { - "@aws-sdk/types": "3.433.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^3.0.8", - "@smithy/signature-v4": "^2.0.0", - "@smithy/types": "^2.4.0", - "@smithy/util-middleware": "^2.0.5", + "@aws-sdk/types": "3.523.0", + "@smithy/protocol-http": "^3.2.1", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -1055,14 +1132,14 @@ } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.438.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.438.0.tgz", - "integrity": "sha512-a+xHT1wOxT6EA6YyLmrfaroKWOkwwyiktUfXKM0FsUutGzNi4fKhb5NZ2al58NsXzHgHFrasSDp+Lqbd/X2cEw==", - "dependencies": { - "@aws-sdk/types": "3.433.0", - "@aws-sdk/util-endpoints": "3.438.0", - "@smithy/protocol-http": "^3.0.8", - "@smithy/types": "^2.4.0", + "version": "3.525.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.525.0.tgz", + "integrity": "sha512-4al/6uO+t/QIYXK2OgqzDKQzzLAYJza1vWFS+S0lJ3jLNGyLB5BMU5KqWjDzevYZ4eCnz2Nn7z0FveUTNz8YdQ==", + "dependencies": { + "@aws-sdk/types": "3.523.0", + "@aws-sdk/util-endpoints": "3.525.0", + "@smithy/protocol-http": "^3.2.1", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -1070,14 +1147,15 @@ } }, "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.433.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.433.0.tgz", - "integrity": "sha512-xpjRjCZW+CDFdcMmmhIYg81ST5UAnJh61IHziQEk0FXONrg4kjyYPZAOjEdzXQ+HxJQuGQLKPhRdzxmQnbX7pg==", - "dependencies": { - "@smithy/node-config-provider": "^2.1.3", - "@smithy/types": "^2.4.0", - "@smithy/util-config-provider": "^2.0.0", - "@smithy/util-middleware": "^2.0.5", + "version": "3.525.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.525.0.tgz", + "integrity": "sha512-8kFqXk6UyKgTMi7N7QlhA6qM4pGPWbiUXqEY2RgUWngtxqNFGeM9JTexZeuavQI+qLLe09VPShPNX71fEDcM6w==", + "dependencies": { + "@aws-sdk/types": "3.523.0", + "@smithy/node-config-provider": "^2.2.4", + "@smithy/types": "^2.10.1", + "@smithy/util-config-provider": "^2.2.1", + "@smithy/util-middleware": "^2.1.3", "tslib": "^2.5.0" }, "engines": { @@ -1085,46 +1163,15 @@ } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.438.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.438.0.tgz", - "integrity": "sha512-G2fUfTtU6/1ayYRMu0Pd9Ln4qYSvwJOWCqJMdkDgvXSwdgcOSOLsnAIk1AHGJDAvgLikdCzuyOsdJiexr9Vnww==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.433.0", - "@aws-sdk/middleware-logger": "3.433.0", - "@aws-sdk/middleware-recursion-detection": "3.433.0", - "@aws-sdk/middleware-user-agent": "3.438.0", - "@aws-sdk/region-config-resolver": "3.433.0", - "@aws-sdk/types": "3.433.0", - "@aws-sdk/util-endpoints": "3.438.0", - "@aws-sdk/util-user-agent-browser": "3.433.0", - "@aws-sdk/util-user-agent-node": "3.437.0", - "@smithy/config-resolver": "^2.0.16", - "@smithy/fetch-http-handler": "^2.2.4", - "@smithy/hash-node": "^2.0.12", - "@smithy/invalid-dependency": "^2.0.12", - "@smithy/middleware-content-length": "^2.0.14", - "@smithy/middleware-endpoint": "^2.1.3", - "@smithy/middleware-retry": "^2.0.18", - "@smithy/middleware-serde": "^2.0.12", - "@smithy/middleware-stack": "^2.0.6", - "@smithy/node-config-provider": "^2.1.3", - "@smithy/node-http-handler": "^2.1.8", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^3.0.8", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/smithy-client": "^2.1.12", - "@smithy/types": "^2.4.0", - "@smithy/url-parser": "^2.0.12", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-body-length-browser": "^2.0.0", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.16", - "@smithy/util-defaults-mode-node": "^2.0.21", - "@smithy/util-endpoints": "^1.0.2", - "@smithy/util-retry": "^2.0.5", - "@smithy/util-utf8": "^2.0.0", + "version": "3.525.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.525.0.tgz", + "integrity": "sha512-puVjbxuK0Dq7PTQ2HdddHy2eQjOH8GZbump74yWJa6JVpRW84LlOcNmP+79x4Kscvz2ldWB8XDFw/pcCiSDe5A==", + "dependencies": { + "@aws-sdk/client-sso-oidc": "3.525.0", + "@aws-sdk/types": "3.523.0", + "@smithy/property-provider": "^2.1.3", + "@smithy/shared-ini-file-loader": "^2.3.3", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -1132,11 +1179,11 @@ } }, "node_modules/@aws-sdk/types": { - "version": "3.433.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.433.0.tgz", - "integrity": "sha512-0jEE2mSrNDd8VGFjTc1otYrwYPIkzZJEIK90ZxisKvQ/EURGBhNzWn7ejWB9XCMFT6XumYLBR0V9qq5UPisWtA==", + "version": "3.523.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.523.0.tgz", + "integrity": "sha512-AqGIu4u+SxPiUuNBp2acCVcq80KDUFjxe6e3cMTvKWTzCbrVk1AXv0dAaJnCmdkWIha6zJDWxpIk/aL4EGhZ9A==", "dependencies": { - "@smithy/types": "^2.4.0", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -1169,9 +1216,10 @@ } }, "node_modules/@aws-sdk/util-dynamodb": { - "version": "3.438.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.438.0.tgz", - "integrity": "sha512-K0r30mLy3iQe3qQVJxJAp+eOuoCmrO5KVodBoC5VT1ivjtYIgGxzUWphKhaqcASjmaE+Lg0UjHKjxWGOyAEC4A==", + "version": "3.528.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-dynamodb/-/util-dynamodb-3.528.0.tgz", + "integrity": "sha512-RSSFtTWqJOeZHDtaSXd51LIP3Xu0mDPYc1Eu+LJXEC2GHWYDdjoeAMpIJvETBg13bBWkRgHatujT8tLFxCx1ug==", + "dev": true, "dependencies": { "tslib": "^2.5.0" }, @@ -1183,12 +1231,13 @@ } }, "node_modules/@aws-sdk/util-endpoints": { - "version": "3.438.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.438.0.tgz", - "integrity": "sha512-6VyPTq1kN3GWxwFt5DdZfOsr6cJZPLjWh0troY/0uUv3hK74C9o3Y0Xf/z8UAUvQFkVqZse12O0/BgPVMImvfA==", + "version": "3.525.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.525.0.tgz", + "integrity": "sha512-DIW7WWU5tIGkeeKX6NJUyrEIdWMiqjLQG3XBzaUj+ufIENwNjdAHhlD8l2vX7Yr3JZRT6yN/84wBCj7Tw1xd1g==", "dependencies": { - "@aws-sdk/types": "3.433.0", - "@smithy/util-endpoints": "^1.0.2", + "@aws-sdk/types": "3.523.0", + "@smithy/types": "^2.10.1", + "@smithy/util-endpoints": "^1.1.4", "tslib": "^2.5.0" }, "engines": { @@ -1196,9 +1245,9 @@ } }, "node_modules/@aws-sdk/util-locate-window": { - "version": "3.310.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz", - "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==", + "version": "3.465.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.465.0.tgz", + "integrity": "sha512-f+QNcWGswredzC1ExNAB/QzODlxwaTdXkNT5cvke2RLX8SFU5pYk6h4uCtWC0vWPELzOfMfloBrJefBzlarhsw==", "dependencies": { "tslib": "^2.5.0" }, @@ -1207,24 +1256,24 @@ } }, "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.433.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.433.0.tgz", - "integrity": "sha512-2Cf/Lwvxbt5RXvWFXrFr49vXv0IddiUwrZoAiwhDYxvsh+BMnh+NUFot+ZQaTrk/8IPZVDeLPWZRdVy00iaVXQ==", + "version": "3.523.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.523.0.tgz", + "integrity": "sha512-6ZRNdGHX6+HQFqTbIA5+i8RWzxFyxsZv8D3soRfpdyWIKkzhSz8IyRKXRciwKBJDaC7OX2jzGE90wxRQft27nA==", "dependencies": { - "@aws-sdk/types": "3.433.0", - "@smithy/types": "^2.4.0", + "@aws-sdk/types": "3.523.0", + "@smithy/types": "^2.10.1", "bowser": "^2.11.0", "tslib": "^2.5.0" } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.437.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.437.0.tgz", - "integrity": "sha512-JVEcvWaniamtYVPem4UthtCNoTBCfFTwYj7Y3CrWZ2Qic4TqrwLkAfaBGtI2TGrhIClVr77uzLI6exqMTN7orA==", + "version": "3.525.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.525.0.tgz", + "integrity": "sha512-88Wjt4efyUSBGcyIuh1dvoMqY1k15jpJc5A/3yi67clBQEFsu9QCodQCQPqmRjV3VRcMtBOk+jeCTiUzTY5dRQ==", "dependencies": { - "@aws-sdk/types": "3.433.0", - "@smithy/node-config-provider": "^2.1.3", - "@smithy/types": "^2.4.0", + "@aws-sdk/types": "3.523.0", + "@smithy/node-config-provider": "^2.2.4", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -1248,12 +1297,12 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.13", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -1332,30 +1381,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.20.tgz", - "integrity": "sha512-BQYjKbpXjoXwFW5jGqiizJQQT/aC7pFm9Ok1OWssonuguICi264lbgMzRp2ZMmRSlfkX6DsWDDcsrctK8Rwfiw==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.0.tgz", - "integrity": "sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==", + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.7.tgz", + "integrity": "sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.23.0", - "@babel/helpers": "^7.23.0", - "@babel/parser": "^7.23.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.23.7", + "@babel/parser": "^7.23.6", "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.0", - "@babel/types": "^7.23.0", + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -1380,12 +1429,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", "dev": true, "dependencies": { - "@babel/types": "^7.23.0", + "@babel/types": "^7.23.6", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -1395,14 +1444,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", - "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.15", - "browserslist": "^4.21.9", + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -1466,9 +1515,9 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", - "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", + "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", @@ -1518,9 +1567,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -1536,32 +1585,32 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", - "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.23.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.1.tgz", - "integrity": "sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==", + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.8.tgz", + "integrity": "sha512-KDqYz4PiOWvDFrdHLPhKtCThtIcKVy6avWD2oG4GEvyQ+XDZwHD4YQd+H2vNMnq2rkdxsDkU82T+Vk8U/WXHRQ==", "dev": true, "dependencies": { "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.0", - "@babel/types": "^7.23.0" + "@babel/traverse": "^7.23.7", + "@babel/types": "^7.23.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", @@ -1644,9 +1693,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", + "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -1716,9 +1765,9 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", - "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz", + "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1818,9 +1867,9 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", - "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "version": "7.23.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz", + "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.22.5" @@ -1847,20 +1896,20 @@ } }, "node_modules/@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz", + "integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", + "@babel/parser": "^7.23.6", + "@babel/types": "^7.23.6", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -1877,12 +1926,12 @@ } }, "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz", + "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, @@ -1918,10 +1967,25 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.1.tgz", + "integrity": "sha512-m55cpeupQ2DbuRGQMMZDzbv9J9PgVelPjlcmM5kxHnrBdBx6REaEd7LamYV7Dm8N7rCyR/XwU6rVP8ploKtIkA==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/android-arm": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.3.tgz", - "integrity": "sha512-Lemgw4io4VZl9GHJmjiBGzQ7ONXRfRPHcUEerndjwiSkbxzrpq0Uggku5MxxrXdwJ+pTj1qyw4jwTu7hkPsgIA==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.1.tgz", + "integrity": "sha512-4j0+G27/2ZXGWR5okcJi7pQYhmkVgb4D7UKwxcqrjhvp5TKWx3cUjgB1CGj1mfdmJBQ9VnUGgUhign+FPF2Zgw==", "cpu": [ "arm" ], @@ -1934,9 +1998,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.3.tgz", - "integrity": "sha512-w+Akc0vv5leog550kjJV9Ru+MXMR2VuMrui3C61mnysim0gkFCPOUTAfzTP0qX+HpN9Syu3YA3p1hf3EPqObRw==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.1.tgz", + "integrity": "sha512-hCnXNF0HM6AjowP+Zou0ZJMWWa1VkD77BXe959zERgGJBBxB+sV+J9f/rcjeg2c5bsukD/n17RKWXGFCO5dD5A==", "cpu": [ "arm64" ], @@ -1949,9 +2013,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.3.tgz", - "integrity": "sha512-FKQJKkK5MXcBHoNZMDNUAg1+WcZlV/cuXrWCoGF/TvdRiYS4znA0m5Il5idUwfxrE20bG/vU1Cr5e1AD6IEIjQ==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.1.tgz", + "integrity": "sha512-MSfZMBoAsnhpS+2yMFYIQUPs8Z19ajwfuaSZx+tSl09xrHZCjbeXXMsUF/0oq7ojxYEpsSo4c0SfjxOYXRbpaA==", "cpu": [ "x64" ], @@ -1964,9 +2028,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.3.tgz", - "integrity": "sha512-kw7e3FXU+VsJSSSl2nMKvACYlwtvZB8RUIeVShIEY6PVnuZ3c9+L9lWB2nWeeKWNNYDdtL19foCQ0ZyUL7nqGw==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.1.tgz", + "integrity": "sha512-Ylk6rzgMD8klUklGPzS414UQLa5NPXZD5tf8JmQU8GQrj6BrFA/Ic9tb2zRe1kOZyCbGl+e8VMbDRazCEBqPvA==", "cpu": [ "arm64" ], @@ -1979,9 +2043,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.3.tgz", - "integrity": "sha512-tPfZiwF9rO0jW6Jh9ipi58N5ZLoSjdxXeSrAYypy4psA2Yl1dAMhM71KxVfmjZhJmxRjSnb29YlRXXhh3GqzYw==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.1.tgz", + "integrity": "sha512-pFIfj7U2w5sMp52wTY1XVOdoxw+GDwy9FsK3OFz4BpMAjvZVs0dT1VXs8aQm22nhwoIWUmIRaE+4xow8xfIDZA==", "cpu": [ "x64" ], @@ -1994,9 +2058,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.3.tgz", - "integrity": "sha512-ERDyjOgYeKe0Vrlr1iLrqTByB026YLPzTytDTz1DRCYM+JI92Dw2dbpRHYmdqn6VBnQ9Bor6J8ZlNwdZdxjlSg==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.1.tgz", + "integrity": "sha512-UyW1WZvHDuM4xDz0jWun4qtQFauNdXjXOtIy7SYdf7pbxSWWVlqhnR/T2TpX6LX5NI62spt0a3ldIIEkPM6RHw==", "cpu": [ "arm64" ], @@ -2009,9 +2073,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.3.tgz", - "integrity": "sha512-nXesBZ2Ad1qL+Rm3crN7NmEVJ5uvfLFPLJev3x1j3feCQXfAhoYrojC681RhpdOph8NsvKBBwpYZHR7W0ifTTA==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.1.tgz", + "integrity": "sha512-itPwCw5C+Jh/c624vcDd9kRCCZVpzpQn8dtwoYIt2TJF3S9xJLiRohnnNrKwREvcZYx0n8sCSbvGH349XkcQeg==", "cpu": [ "x64" ], @@ -2024,9 +2088,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.3.tgz", - "integrity": "sha512-zr48Cg/8zkzZCzDHNxXO/89bf9e+r4HtzNUPoz4GmgAkF1gFAFmfgOdCbR8zMbzFDGb1FqBBhdXUpcTQRYS1cQ==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.1.tgz", + "integrity": "sha512-LojC28v3+IhIbfQ+Vu4Ut5n3wKcgTu6POKIHN9Wpt0HnfgUGlBuyDDQR4jWZUZFyYLiz4RBBBmfU6sNfn6RhLw==", "cpu": [ "arm" ], @@ -2039,9 +2103,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.3.tgz", - "integrity": "sha512-qXvYKmXj8GcJgWq3aGvxL/JG1ZM3UR272SdPU4QSTzD0eymrM7leiZH77pvY3UetCy0k1xuXZ+VPvoJNdtrsWQ==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.1.tgz", + "integrity": "sha512-cX8WdlF6Cnvw/DO9/X7XLH2J6CkBnz7Twjpk56cshk9sjYVcuh4sXQBy5bmTwzBjNVZze2yaV1vtcJS04LbN8w==", "cpu": [ "arm64" ], @@ -2054,9 +2118,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.3.tgz", - "integrity": "sha512-7XlCKCA0nWcbvYpusARWkFjRQNWNGlt45S+Q18UeS///K6Aw8bB2FKYe9mhVWy/XLShvCweOLZPrnMswIaDXQA==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.1.tgz", + "integrity": "sha512-4H/sQCy1mnnGkUt/xszaLlYJVTz3W9ep52xEefGtd6yXDQbz/5fZE5dFLUgsPdbUOQANcVUa5iO6g3nyy5BJiw==", "cpu": [ "ia32" ], @@ -2069,9 +2133,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.3.tgz", - "integrity": "sha512-qGTgjweER5xqweiWtUIDl9OKz338EQqCwbS9c2Bh5jgEH19xQ1yhgGPNesugmDFq+UUSDtWgZ264st26b3de8A==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.1.tgz", + "integrity": "sha512-c0jgtB+sRHCciVXlyjDcWb2FUuzlGVRwGXgI+3WqKOIuoo8AmZAddzeOHeYLtD+dmtHw3B4Xo9wAUdjlfW5yYA==", "cpu": [ "loong64" ], @@ -2084,9 +2148,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.3.tgz", - "integrity": "sha512-gy1bFskwEyxVMFRNYSvBauDIWNggD6pyxUksc0MV9UOBD138dKTzr8XnM2R4mBsHwVzeuIH8X5JhmNs2Pzrx+A==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.1.tgz", + "integrity": "sha512-TgFyCfIxSujyuqdZKDZ3yTwWiGv+KnlOeXXitCQ+trDODJ+ZtGOzLkSWngynP0HZnTsDyBbPy7GWVXWaEl6lhA==", "cpu": [ "mips64el" ], @@ -2099,9 +2163,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.3.tgz", - "integrity": "sha512-UrYLFu62x1MmmIe85rpR3qou92wB9lEXluwMB/STDzPF9k8mi/9UvNsG07Tt9AqwPQXluMQ6bZbTzYt01+Ue5g==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.1.tgz", + "integrity": "sha512-b+yuD1IUeL+Y93PmFZDZFIElwbmFfIKLKlYI8M6tRyzE6u7oEP7onGk0vZRh8wfVGC2dZoy0EqX1V8qok4qHaw==", "cpu": [ "ppc64" ], @@ -2114,9 +2178,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.3.tgz", - "integrity": "sha512-9E73TfyMCbE+1AwFOg3glnzZ5fBAFK4aawssvuMgCRqCYzE0ylVxxzjEfut8xjmKkR320BEoMui4o/t9KA96gA==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.1.tgz", + "integrity": "sha512-wpDlpE0oRKZwX+GfomcALcouqjjV8MIX8DyTrxfyCfXxoKQSDm45CZr9fanJ4F6ckD4yDEPT98SrjvLwIqUCgg==", "cpu": [ "riscv64" ], @@ -2129,9 +2193,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.3.tgz", - "integrity": "sha512-LlmsbuBdm1/D66TJ3HW6URY8wO6IlYHf+ChOUz8SUAjVTuaisfuwCOAgcxo3Zsu3BZGxmI7yt//yGOxV+lHcEA==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.1.tgz", + "integrity": "sha512-5BepC2Au80EohQ2dBpyTquqGCES7++p7G+7lXe1bAIvMdXm4YYcEfZtQrP4gaoZ96Wv1Ute61CEHFU7h4FMueQ==", "cpu": [ "s390x" ], @@ -2144,9 +2208,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.3.tgz", - "integrity": "sha512-ogV0+GwEmvwg/8ZbsyfkYGaLACBQWDvO0Kkh8LKBGKj9Ru8VM39zssrnu9Sxn1wbapA2qNS6BiLdwJZGouyCwQ==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.1.tgz", + "integrity": "sha512-5gRPk7pKuaIB+tmH+yKd2aQTRpqlf1E4f/mC+tawIm/CGJemZcHZpp2ic8oD83nKgUPMEd0fNanrnFljiruuyA==", "cpu": [ "x64" ], @@ -2159,9 +2223,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.3.tgz", - "integrity": "sha512-o1jLNe4uzQv2DKXMlmEzf66Wd8MoIhLNO2nlQBHLtWyh2MitDG7sMpfCO3NTcoTMuqHjfufgUQDFRI5C+xsXQw==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.1.tgz", + "integrity": "sha512-4fL68JdrLV2nVW2AaWZBv3XEm3Ae3NZn/7qy2KGAt3dexAgSVT+Hc97JKSZnqezgMlv9x6KV0ZkZY7UO5cNLCg==", "cpu": [ "x64" ], @@ -2174,9 +2238,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.3.tgz", - "integrity": "sha512-AZJCnr5CZgZOdhouLcfRdnk9Zv6HbaBxjcyhq0StNcvAdVZJSKIdOiPB9az2zc06ywl0ePYJz60CjdKsQacp5Q==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.1.tgz", + "integrity": "sha512-GhRuXlvRE+twf2ES+8REbeCb/zeikNqwD3+6S5y5/x+DYbAQUNl0HNBs4RQJqrechS4v4MruEr8ZtAin/hK5iw==", "cpu": [ "x64" ], @@ -2189,9 +2253,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.3.tgz", - "integrity": "sha512-Acsujgeqg9InR4glTRvLKGZ+1HMtDm94ehTIHKhJjFpgVzZG9/pIcWW/HA/DoMfEyXmANLDuDZ2sNrWcjq1lxw==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.1.tgz", + "integrity": "sha512-ZnWEyCM0G1Ex6JtsygvC3KUUrlDXqOihw8RicRuQAzw+c4f1D66YlPNNV3rkjVW90zXVsHwZYWbJh3v+oQFM9Q==", "cpu": [ "x64" ], @@ -2204,9 +2268,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.3.tgz", - "integrity": "sha512-FSrAfjVVy7TifFgYgliiJOyYynhQmqgPj15pzLyJk8BUsnlWNwP/IAy6GAiB1LqtoivowRgidZsfpoYLZH586A==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.1.tgz", + "integrity": "sha512-QZ6gXue0vVQY2Oon9WyLFCdSuYbXSoxaZrPuJ4c20j6ICedfsDilNPYfHLlMH7vGfU5DQR0czHLmJvH4Nzis/A==", "cpu": [ "arm64" ], @@ -2219,9 +2283,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.3.tgz", - "integrity": "sha512-xTScXYi12xLOWZ/sc5RBmMN99BcXp/eEf7scUC0oeiRoiT5Vvo9AycuqCp+xdpDyAU+LkrCqEpUS9fCSZF8J3Q==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.1.tgz", + "integrity": "sha512-HzcJa1NcSWTAU0MJIxOho8JftNp9YALui3o+Ny7hCh0v5f90nprly1U3Sj1Ldj/CvKKdvvFsCRvDkpsEMp4DNw==", "cpu": [ "ia32" ], @@ -2234,9 +2298,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.3.tgz", - "integrity": "sha512-FbUN+0ZRXsypPyWE2IwIkVjDkDnJoMJARWOcFZn4KPPli+QnKqF0z1anvfaYe3ev5HFCpRDLLBDHyOALLppWHw==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.1.tgz", + "integrity": "sha512-0MBh53o6XtI6ctDnRMeQ+xoCN8kD2qI1rY1KgF/xdWQwoFeKou7puvDfV8/Wv4Ctx2rRpET/gGdz3YlNtNACSA==", "cpu": [ "x64" ], @@ -2264,18 +2328,18 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.0.tgz", - "integrity": "sha512-zJmuCWj2VLBt4c25CfBIbMZLGLyhkvs7LznyVX5HfpzeocThgIj5XQK4L+g3U36mMcx8bPMhGyPpwCATamC4jQ==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -2295,19 +2359,41 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "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, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@eslint/js": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.50.0.tgz", - "integrity": "sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@faker-js/faker": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.3.1.tgz", - "integrity": "sha512-FdgpFxY6V6rLZE9mmIBb9hM0xpfvQOSNOLnzolzKwsE1DH+gC7lEKV1p1IbR0lAYyvYd5a4u3qWJzowUkw1bIw==", + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.4.1.tgz", + "integrity": "sha512-XQ3cU+Q8Uqmrbf2e0cIC/QN43sTBSC8KF12u29Mb47tWrt2hAgBXSgpZMj4Ao8Uk0iJcU99QsOCaIL8934obCg==", "dev": true, "funding": [ { @@ -2321,19 +2407,41 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", - "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/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, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -2348,9 +2456,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, "node_modules/@hutson/parse-repository-url": { @@ -2883,38 +2991,23 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "version": "0.3.21", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.21.tgz", + "integrity": "sha512-SRfKmRe1KvYnxjEMtxEr+J4HIeMX5YBg/qhRHpxEIGjhX1rshcHlnFUE9K0GazhVKWM7B+nARSkV8LuvJdJ5/g==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@lerna/child-process": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@lerna/child-process/-/child-process-7.3.0.tgz", - "integrity": "sha512-rA+fGUo2j/LEq6w1w8s6oVikLbJTWoIDVpYMc7bUCtwDOUuZKMQiRtjmpavY3fTm7ltu42f4AKflc2A70K4wvA==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "execa": "^5.0.0", - "strong-log-transformer": "^2.1.0" - }, - "engines": { - "node": "^14.17.0 || >=16.0.0" - } - }, "node_modules/@lerna/create": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/@lerna/create/-/create-7.3.0.tgz", - "integrity": "sha512-fjgiKjg9VXwQ4ZKKsrXICEKRiC3yo6+FprR0mc55uz0s5e9xupoSGLobUTTBdE7ncNB3ibqml8dfaAn/+ESajQ==", + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/@lerna/create/-/create-8.1.2.tgz", + "integrity": "sha512-GzScCIkAW3tg3+Yn/MKCH9963bzG+zpjGz2NdfYDlYWI7p0f/SH46v1dqpPpYmZ2E/m3JK8HjTNNNL8eIm8/YQ==", "dev": true, "dependencies": { - "@lerna/child-process": "7.3.0", - "@npmcli/run-script": "6.0.2", - "@nx/devkit": ">=16.5.1 < 17", + "@npmcli/run-script": "7.0.2", + "@nx/devkit": ">=17.1.2 < 19", "@octokit/plugin-enterprise-rest": "6.0.1", "@octokit/rest": "19.0.11", "byte-size": "8.1.1", @@ -2951,12 +3044,12 @@ "npm-packlist": "5.1.1", "npm-registry-fetch": "^14.0.5", "npmlog": "^6.0.2", - "nx": ">=16.5.1 < 17", + "nx": ">=17.1.2 < 19", "p-map": "4.0.0", "p-map-series": "2.1.0", "p-queue": "6.6.2", "p-reduce": "^2.1.0", - "pacote": "^15.2.0", + "pacote": "^17.0.5", "pify": "5.0.0", "read-cmd-shim": "4.0.0", "read-package-json": "6.0.4", @@ -2975,11 +3068,21 @@ "validate-npm-package-name": "5.0.0", "write-file-atomic": "5.0.1", "write-pkg": "4.0.0", - "yargs": "16.2.0", - "yargs-parser": "20.2.4" + "yargs": "17.7.2", + "yargs-parser": "21.1.1" }, "engines": { - "node": "^14.17.0 || >=16.0.0" + "node": ">=18.0.0" + } + }, + "node_modules/@lerna/create/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, "node_modules/@lerna/create/node_modules/chalk": { @@ -3188,29 +3291,10 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@lerna/create/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@middy/core": { - "version": "4.6.5", - "resolved": "https://registry.npmjs.org/@middy/core/-/core-4.6.5.tgz", - "integrity": "sha512-nsAmIcafn2GGHz7yOJecEZjQ0UVARC+Wem2wzGELolXKM2TskcyDcvwqDSlas4pwh7gzHTdfwP+pUmQVRGWJPQ==", - "devOptional": true, + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@middy/core/-/core-4.7.0.tgz", + "integrity": "sha512-yI++DmhDQ8+ugvY7+GrEnb2PF0M/6Wzbgu4Tf7QhOlhwKGDd4j6or+Ab7qYPWx+jnKf8F0tqlmh0gV4JLi0yHw==", "engines": { "node": ">=16" }, @@ -3254,68 +3338,154 @@ "node": ">= 8" } }, - "node_modules/@npmcli/fs": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", - "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", + "node_modules/@npmcli/agent": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@npmcli/agent/-/agent-2.2.1.tgz", + "integrity": "sha512-H4FrOVtNyWC8MUwL3UfjOsAihHvT1Pe8POj3JvjXhSTJipsZMtgUALCT4mGyYZNxymkUfOw3PUj6dE4QPp6osQ==", "dev": true, "dependencies": { - "semver": "^7.3.5" + "agent-base": "^7.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.1", + "lru-cache": "^10.0.1", + "socks-proxy-agent": "^8.0.1" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/@npmcli/git": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.1.0.tgz", - "integrity": "sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==", + "node_modules/@npmcli/agent/node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", "dev": true, "dependencies": { - "@npmcli/promise-spawn": "^6.0.0", - "lru-cache": "^7.4.4", - "npm-pick-manifest": "^8.0.0", - "proc-log": "^3.0.0", - "promise-inflight": "^1.0.1", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^3.0.0" + "debug": "^4.3.4" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">= 14" } }, - "node_modules/@npmcli/git/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "node_modules/@npmcli/agent/node_modules/http-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", "dev": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, "engines": { - "node": ">=12" + "node": ">= 14" } }, - "node_modules/@npmcli/git/node_modules/which": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", - "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "node_modules/@npmcli/agent/node_modules/https-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", + "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", "dev": true, "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/which.js" + "agent-base": "^7.0.2", + "debug": "4" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">= 14" } }, - "node_modules/@npmcli/installed-package-contents": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz", - "integrity": "sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==", + "node_modules/@npmcli/agent/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", "dev": true, - "dependencies": { - "npm-bundled": "^3.0.0", + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/@npmcli/agent/node_modules/socks-proxy-agent": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.2.tgz", + "integrity": "sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==", + "dev": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@npmcli/fs": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", + "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", + "dev": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/git": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-5.0.4.tgz", + "integrity": "sha512-nr6/WezNzuYUppzXRaYu/W4aT5rLxdXqEFupbh6e/ovlYFQ8hpu1UUPV3Ir/YTl+74iXl2ZOMlGzudh9ZPUchQ==", + "dev": true, + "dependencies": { + "@npmcli/promise-spawn": "^7.0.0", + "lru-cache": "^10.0.1", + "npm-pick-manifest": "^9.0.0", + "proc-log": "^3.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^4.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/git/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/@npmcli/git/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/@npmcli/git/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", + "dev": true, + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/installed-package-contents": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz", + "integrity": "sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==", + "dev": true, + "dependencies": { + "npm-bundled": "^3.0.0", "npm-normalize-package-bin": "^3.0.0" }, "bin": { @@ -3356,79 +3526,97 @@ } }, "node_modules/@npmcli/promise-spawn": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz", - "integrity": "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-7.0.1.tgz", + "integrity": "sha512-P4KkF9jX3y+7yFUxgcUdDtLy+t4OlDGuEBLNs57AZsfSfg+uV6MLndqGpnl4831ggaEdXwR50XFoZP4VFtHolg==", "dev": true, "dependencies": { - "which": "^3.0.0" + "which": "^4.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/promise-spawn/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "engines": { + "node": ">=16" } }, "node_modules/@npmcli/promise-spawn/node_modules/which": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", - "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", "dev": true, "dependencies": { - "isexe": "^2.0.0" + "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^16.13.0 || >=18.0.0" } }, "node_modules/@npmcli/run-script": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-6.0.2.tgz", - "integrity": "sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-7.0.2.tgz", + "integrity": "sha512-Omu0rpA8WXvcGeY6DDzyRoY1i5DkCBkzyJ+m2u7PD6quzb0TvSqdIPOkTn8ZBOj7LbbcbMfZ3c5skwSu6m8y2w==", "dev": true, "dependencies": { "@npmcli/node-gyp": "^3.0.0", - "@npmcli/promise-spawn": "^6.0.0", - "node-gyp": "^9.0.0", + "@npmcli/promise-spawn": "^7.0.0", + "node-gyp": "^10.0.0", "read-package-json-fast": "^3.0.0", - "which": "^3.0.0" + "which": "^4.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/run-script/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "engines": { + "node": ">=16" } }, "node_modules/@npmcli/run-script/node_modules/which": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", - "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", "dev": true, "dependencies": { - "isexe": "^2.0.0" + "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^16.13.0 || >=18.0.0" } }, "node_modules/@nrwl/devkit": { - "version": "16.9.1", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-16.9.1.tgz", - "integrity": "sha512-+iR7tg+LOrGWAGmGv0hr45hYUOeKjK/Jm6WV3Ldmx6I7LaaYM5Fu6Ev2KXL669QMzLJpg3kqgKQsneWbFT3MAw==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-18.0.3.tgz", + "integrity": "sha512-ztDAaiEciEL4Gwq42m6+gz392QnBRBZoYwYUEXhLiOrPngAu2eGnkXrQlSvF54ISKLwzD7gnGAKRzpA6nw8u5w==", "dev": true, "dependencies": { - "@nx/devkit": "16.9.1" + "@nx/devkit": "18.0.3" } }, "node_modules/@nrwl/tao": { - "version": "16.9.1", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-16.9.1.tgz", - "integrity": "sha512-KsRBRAE5mSP83ZjO9cPW6ZQZWOtkMfCBih/WE9qpaiHn+hCydtYStyAO2QSic4tHVV+8VpPUQWYnpf5rhkNzWg==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-18.0.3.tgz", + "integrity": "sha512-9EIIkjvaXs7JM0shhZAQIblV3ym+wZyqxZ9nYc39OwPkII2xXtGhWPhd7SRj+If6lbVNpelIc/Xg5DpTMgu16g==", "dev": true, "dependencies": { - "nx": "16.9.1", + "nx": "18.0.3", "tslib": "^2.3.0" }, "bin": { @@ -3436,60 +3624,28 @@ } }, "node_modules/@nx/devkit": { - "version": "16.9.1", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-16.9.1.tgz", - "integrity": "sha512-jQMLX8pUKsOIk0tLFzJms5awPxKfJEi0uxY7+IUfRNHcnDkOFiv6gf1QqJ3pobmgwBdbC6Nv/dhDP3JT2wA1gA==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-18.0.3.tgz", + "integrity": "sha512-HiQq43YHfdjG5WnBxVNTlRm1IhnVaWoBLZrbkFItElX4SIhUqWQUp0gjtdTXy0do8Q2hkj8aITrC4Tm92KiyUw==", "dev": true, "dependencies": { - "@nrwl/devkit": "16.9.1", + "@nrwl/devkit": "18.0.3", "ejs": "^3.1.7", "enquirer": "~2.3.6", "ignore": "^5.0.4", - "semver": "7.5.3", + "semver": "^7.5.3", "tmp": "~0.2.1", - "tslib": "^2.3.0" + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" }, "peerDependencies": { - "nx": ">= 15 <= 17" - } - }, - "node_modules/@nx/devkit/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@nx/devkit/node_modules/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "nx": ">= 16 <= 18" } }, - "node_modules/@nx/devkit/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/@nx/nx-darwin-arm64": { - "version": "16.9.1", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-16.9.1.tgz", - "integrity": "sha512-JWGrPxxt3XjgIYzvnaNAeNmK24wyF6yEE1bV+wnnKzd7yavVps3c2TOVE/AT4sgvdVj3xFzztyixYGV58tCYrg==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-18.0.3.tgz", + "integrity": "sha512-fsMzaX848KMNyF3+I5JjayHFKPsANsbr/++qTIc9skMLPYz1DQANcD6TSkc1tOWLSn4CV44cEAIwfAddPEBupw==", "cpu": [ "arm64" ], @@ -3503,9 +3659,9 @@ } }, "node_modules/@nx/nx-darwin-x64": { - "version": "16.9.1", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-16.9.1.tgz", - "integrity": "sha512-b1Hw1AmKrR+Kp361WTiKC1RFoQwERyW9R/9XJGNIdgtr+V2wa775eCEdxB9r9mwCqyEmM9iVadpRHPaFSAfQfQ==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-18.0.3.tgz", + "integrity": "sha512-W/FcvpQcBmsHuTcLQ2BwVjgARqTzGgLEqUGs6S/PnSEL+IgoBaWvQMavOoiisv8QY9GlLzX5Oq3rAkpJ1EmoNw==", "cpu": [ "x64" ], @@ -3519,9 +3675,9 @@ } }, "node_modules/@nx/nx-freebsd-x64": { - "version": "16.9.1", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-16.9.1.tgz", - "integrity": "sha512-jscl/Xu86tLQYbC8b1wy9FjEgGyuLpYnvP9d+34AHDi6CbCNSodbv93xFDlfYcLOeOD/mJXqR1Ru/1MF86OB5A==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-18.0.3.tgz", + "integrity": "sha512-Wx+nRQdQQsXd8DvAy426AtPoo80F3Loku+r8AKp1QBT24NCPzD/yjz6bGyNucGCrt+RKGPmaFHWBw+8qByMi6A==", "cpu": [ "x64" ], @@ -3535,9 +3691,9 @@ } }, "node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "16.9.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-16.9.1.tgz", - "integrity": "sha512-NMAyxjYv9y4LwzU76htcPWfdmRoN/ZziTNKT3jaMbn38x4e7DoXYs9GGh267z45yWHscQWoV0v+X39LmB819aQ==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-18.0.3.tgz", + "integrity": "sha512-oM2Yraf2JVaLyT8GLUnwGKiIyB5WIi07TbJs9kLiZz1HAoJs6pG9kwrilHoS8o1t1jNR87pYbyfO1nRpa8ZR0Q==", "cpu": [ "arm" ], @@ -3551,9 +3707,9 @@ } }, "node_modules/@nx/nx-linux-arm64-gnu": { - "version": "16.9.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-16.9.1.tgz", - "integrity": "sha512-A5UbK5rFhqzs3kMiEKA+xr3LAJsQBA97VDyMH6WPraSl+XRIt4EePx0MyEqo1pnEgeuoOCvR1tjDot5E7ldInw==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-18.0.3.tgz", + "integrity": "sha512-z5T32HcsoaTUazDiN0HSMSxnuw3W2GG1ASvqaWOn+LU7pCDasPFSVylJx68hNEjo9dYMBg9OCHyuhffwi8ZlOg==", "cpu": [ "arm64" ], @@ -3567,9 +3723,9 @@ } }, "node_modules/@nx/nx-linux-arm64-musl": { - "version": "16.9.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-16.9.1.tgz", - "integrity": "sha512-eIn5PnKH7Y/u1LuanAM0wPNdcb9Z7seDjQzQ0hFMCCvV75Z8A02ztbiueLGaEsDLx35MPBdBmuyo4hsmvmLgpg==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-18.0.3.tgz", + "integrity": "sha512-1t85YQEPsOSjEWGiho4zuQMH6Zb24yCbAVJJPZpKzASQzOvv+0ayITkY7P4OaJ84oZ9T/GojXmYnINAePTlrNQ==", "cpu": [ "arm64" ], @@ -3583,9 +3739,9 @@ } }, "node_modules/@nx/nx-linux-x64-gnu": { - "version": "16.9.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-16.9.1.tgz", - "integrity": "sha512-MMvhoS1pZjyIjwfeZNH2dDZuVF2xxURLTXC4UmmpY/wOWCuXhvD7QUv5A5QShxfaVXmXceo/fGLK+/Qm5e2+7g==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-18.0.3.tgz", + "integrity": "sha512-4sS6mnLt+PGG8oYmV91tvLuAu7jh1YrRuZQlv166nVS61TI0V0oaNREdxUZF92WpvavDA1ftXEImcASEex6n3Q==", "cpu": [ "x64" ], @@ -3599,9 +3755,9 @@ } }, "node_modules/@nx/nx-linux-x64-musl": { - "version": "16.9.1", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-16.9.1.tgz", - "integrity": "sha512-ca0d00YCHo0+OIT80MZdtseJj9wTlWMucmdm0OCXLf/l+Dma4MO4LR09WMH2VIpjoz4Gj7+xP0QtKtH4fWFD8Q==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-18.0.3.tgz", + "integrity": "sha512-VmiNOH4/dYOQ5X8DaHrmTZyzrIbCUgHE7oco1pRBPEHkid8E0WyvD9sZLCVEipV80Av9nhOaQ1srAtcfOxchVQ==", "cpu": [ "x64" ], @@ -3615,9 +3771,9 @@ } }, "node_modules/@nx/nx-win32-arm64-msvc": { - "version": "16.9.1", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-16.9.1.tgz", - "integrity": "sha512-UIDAWH6/LfouFaXLJWyZKggzH/698lSrLkEE1fa9VrrGEOhumk7MPAVQc/XxgkWgPDDR1TJl0ij+J1bOREn73Q==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-18.0.3.tgz", + "integrity": "sha512-ymqpAyJ86I5LzFa4O7FByl770U3R//s1nFsrAz9mDm1AIq5uQyyW+EOMJzJwzm0JinRnwtxiK/GdjgWM6dNSDg==", "cpu": [ "arm64" ], @@ -3631,9 +3787,9 @@ } }, "node_modules/@nx/nx-win32-x64-msvc": { - "version": "16.9.1", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-16.9.1.tgz", - "integrity": "sha512-isnElU5RaQEGPAJhx6VNY0P/avD79s146kmZOn1Ff5fAjReqR7kRxSWXQOdIqc6nPH9Y0c9wNwEAuhBJoor+Mw==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-18.0.3.tgz", + "integrity": "sha512-JkBx64Lg7Ezyr6RML/ajOdy9/NIbVO5dI5bG9ZmryeS5mnUPFBY0ExspL0t4X/ud+F4Sh7gN7uGanNd32wRD1Q==", "cpu": [ "x64" ], @@ -3823,24 +3979,6 @@ "@octokit/openapi-types": "^18.0.0" } }, - "node_modules/@parcel/watcher": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.0.4.tgz", - "integrity": "sha512-cTDi+FUDBIUOBKEtj+nhiJ71AZVlkAsQFuGQTun5tV9mwQBQgZvhCzG+URPQc8myeN32yRVZEfVAPCs1RW+Jvg==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "node-addon-api": "^3.2.1", - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -3851,19 +3989,11 @@ "node": ">=14" } }, - "node_modules/@pkgr/utils": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz", - "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==", + "node_modules/@pkgr/core": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.0.tgz", + "integrity": "sha512-Zwq5OCzuwJC2jwqmpEQt7Ds1DTi6BWSwoGkbb1n9pO3hzb35BoJELx7c0T23iDkBGkh2e7tvOtjF3tr3OaQHDQ==", "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "fast-glob": "^3.3.0", - "is-glob": "^4.0.3", - "open": "^9.1.0", - "picocolors": "^1.0.0", - "tslib": "^2.6.0" - }, "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, @@ -3871,36 +4001,6 @@ "url": "https://opencollective.com/unts" } }, - "node_modules/@pkgr/utils/node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@pkgr/utils/node_modules/open": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", - "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", - "dev": true, - "dependencies": { - "default-browser": "^4.0.0", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@sigstore/bundle": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-1.1.0.tgz", @@ -3913,6 +4013,15 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/@sigstore/core": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-1.0.0.tgz", + "integrity": "sha512-dW2qjbWLRKGu6MIDUTBuJwXCnR8zivcSpf5inUzk7y84zqy/dji0/uahppoIgMoKeR+6pUZucrwHfkQQtiG9Rw==", + "dev": true, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, "node_modules/@sigstore/protobuf-specs": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.2.1.tgz", @@ -3936,61 +4045,227 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/@sigstore/tuf": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-1.0.3.tgz", - "integrity": "sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==", + "node_modules/@sigstore/sign/node_modules/cacache": { + "version": "17.1.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", + "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", "dev": true, "dependencies": { - "@sigstore/protobuf-specs": "^0.2.0", - "tuf-js": "^1.1.7" + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^7.7.1", + "minipass": "^7.0.3", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true + "node_modules/@sigstore/sign/node_modules/cacache/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } }, - "node_modules/@sinonjs/commons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", - "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "node_modules/@sigstore/sign/node_modules/fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", "dev": true, "dependencies": { - "type-detect": "4.0.8" + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "node_modules/@sigstore/sign/node_modules/fs-minipass/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", "dev": true, - "dependencies": { - "@sinonjs/commons": "^3.0.0" + "engines": { + "node": ">=16 || 14 >=14.17" } }, - "node_modules/@sinonjs/samsam": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-7.0.1.tgz", - "integrity": "sha512-zsAk2Jkiq89mhZovB2LLOdTCxJF4hqqTToGP0ASWlhp4I1hqOjcfmZGafXntCN7MDC6yySH0mFHrYtHceOeLmw==", + "node_modules/@sigstore/sign/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "dev": true, "dependencies": { - "@sinonjs/commons": "^2.0.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "node_modules/@sigstore/sign/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true, - "dependencies": { - "type-detect": "4.0.8" + "engines": { + "node": ">=12" + } + }, + "node_modules/@sigstore/sign/node_modules/make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/sign/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@sigstore/sign/node_modules/ssri": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", + "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/sign/node_modules/ssri/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/@sigstore/tuf": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-1.0.3.tgz", + "integrity": "sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==", + "dev": true, + "dependencies": { + "@sigstore/protobuf-specs": "^0.2.0", + "tuf-js": "^1.1.7" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/verify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-1.0.0.tgz", + "integrity": "sha512-sRU6nblDBQ4pVTWni019Kij+XQj4RP75WXN5z3qHk81dt/L8A7r3v8RgRInTup4/Jf90WNods9CcbnWj7zJ26w==", + "dev": true, + "dependencies": { + "@sigstore/bundle": "^2.1.1", + "@sigstore/core": "^1.0.0", + "@sigstore/protobuf-specs": "^0.2.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/verify/node_modules/@sigstore/bundle": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-2.1.1.tgz", + "integrity": "sha512-v3/iS+1nufZdKQ5iAlQKcCsoh0jffQyABvYIxKsZQFWc4ubuGjwZklFHpDgV6O6T7vvV78SW5NHI91HFKEcxKg==", + "dev": true, + "dependencies": { + "@sigstore/protobuf-specs": "^0.2.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@sinonjs/samsam": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.0.tgz", + "integrity": "sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^2.0.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", + "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" } }, "node_modules/@sinonjs/text-encoding": { @@ -4000,11 +4275,11 @@ "dev": true }, "node_modules/@smithy/abort-controller": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.12.tgz", - "integrity": "sha512-YIJyefe1mi3GxKdZxEBEuzYOeQ9xpYfqnFmWzojCssRAuR7ycxwpoRQgp965vuW426xUAQhCV5rCaWElQ7XsaA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.1.3.tgz", + "integrity": "sha512-c2aYH2Wu1RVE3rLlVgg2kQOBJGM0WbjReQi5DnPTm2Zb7F0gk7J2aeQeaX2u/lQZoHl6gv8Oac7mt9alU3+f4A==", "dependencies": { - "@smithy/types": "^2.4.0", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -4012,14 +4287,32 @@ } }, "node_modules/@smithy/config-resolver": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.16.tgz", - "integrity": "sha512-1k+FWHQDt2pfpXhJsOmNMmlAZ3NUQ98X5tYsjQhVGq+0X6cOBMhfh6Igd0IX3Ut6lEO6DQAdPMI/blNr3JZfMQ==", - "dependencies": { - "@smithy/node-config-provider": "^2.1.3", - "@smithy/types": "^2.4.0", - "@smithy/util-config-provider": "^2.0.0", - "@smithy/util-middleware": "^2.0.5", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.1.4.tgz", + "integrity": "sha512-AW2WUZmBAzgO3V3ovKtsUbI3aBNMeQKFDumoqkNxaVDWF/xfnxAWqBKDr/NuG7c06N2Rm4xeZLPiJH/d+na0HA==", + "dependencies": { + "@smithy/node-config-provider": "^2.2.4", + "@smithy/types": "^2.10.1", + "@smithy/util-config-provider": "^2.2.1", + "@smithy/util-middleware": "^2.1.3", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/core": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-1.3.5.tgz", + "integrity": "sha512-Rrc+e2Jj6Gu7Xbn0jvrzZlSiP2CZocIOfZ9aNUA82+1sa6GBnxqL9+iZ9EKHeD9aqD1nU8EK4+oN2EiFpSv7Yw==", + "dependencies": { + "@smithy/middleware-endpoint": "^2.4.4", + "@smithy/middleware-retry": "^2.1.4", + "@smithy/middleware-serde": "^2.1.3", + "@smithy/protocol-http": "^3.2.1", + "@smithy/smithy-client": "^2.4.2", + "@smithy/types": "^2.10.1", + "@smithy/util-middleware": "^2.1.3", "tslib": "^2.5.0" }, "engines": { @@ -4027,14 +4320,14 @@ } }, "node_modules/@smithy/credential-provider-imds": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.0.18.tgz", - "integrity": "sha512-QnPBi6D2zj6AHJdUTo5zXmk8vwHJ2bNevhcVned1y+TZz/OI5cizz5DsYNkqFUIDn8tBuEyKNgbmKVNhBbuY3g==", - "dependencies": { - "@smithy/node-config-provider": "^2.1.3", - "@smithy/property-provider": "^2.0.13", - "@smithy/types": "^2.4.0", - "@smithy/url-parser": "^2.0.12", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.2.4.tgz", + "integrity": "sha512-DdatjmBZQnhGe1FhI8gO98f7NmvQFSDiZTwC3WMvLTCKQUY+Y1SVkhJqIuLu50Eb7pTheoXQmK+hKYUgpUWsNA==", + "dependencies": { + "@smithy/node-config-provider": "^2.2.4", + "@smithy/property-provider": "^2.1.3", + "@smithy/types": "^2.10.1", + "@smithy/url-parser": "^2.1.3", "tslib": "^2.5.0" }, "engines": { @@ -4042,23 +4335,23 @@ } }, "node_modules/@smithy/eventstream-codec": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.12.tgz", - "integrity": "sha512-ZZQLzHBJkbiAAdj2C5K+lBlYp/XJ+eH2uy+jgJgYIFW/o5AM59Hlj7zyI44/ZTDIQWmBxb3EFv/c5t44V8/g8A==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.1.3.tgz", + "integrity": "sha512-rGlCVuwSDv6qfKH4/lRxFjcZQnIE0LZ3D4lkMHg7ZSltK9rA74r0VuGSvWVQ4N/d70VZPaniFhp4Z14QYZsa+A==", "dependencies": { "@aws-crypto/crc32": "3.0.0", - "@smithy/types": "^2.4.0", - "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/types": "^2.10.1", + "@smithy/util-hex-encoding": "^2.1.1", "tslib": "^2.5.0" } }, "node_modules/@smithy/eventstream-serde-browser": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.0.12.tgz", - "integrity": "sha512-0pi8QlU/pwutNshoeJcbKR1p7Ie5STd8UFAMX5xhSoSJjNlxIv/OsHbF023jscMRN2Prrqd6ToGgdCnsZVQjvg==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.1.3.tgz", + "integrity": "sha512-qAgKbZ9m2oBfSyJWWurX/MvQFRPrYypj79cDSleEgDwBoez6Tfd+FTpu2L/j3ZeC3mDlDHIKWksoeaXZpLLAHw==", "dependencies": { - "@smithy/eventstream-serde-universal": "^2.0.12", - "@smithy/types": "^2.4.0", + "@smithy/eventstream-serde-universal": "^2.1.3", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -4066,11 +4359,11 @@ } }, "node_modules/@smithy/eventstream-serde-config-resolver": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.0.12.tgz", - "integrity": "sha512-I0XfwQkIX3gAnbrU5rLMkBSjTM9DHttdbLwf12CXmj7SSI5dT87PxtKLRrZGanaCMbdf2yCep+MW5/4M7IbvQA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.1.3.tgz", + "integrity": "sha512-48rvsNv/MgAFCxOE0qwR7ZwKhaEdDoTxqH5HM+T6SDxICmPGb7gEuQzjTxQhcieCPgqyXeZFW8cU0QJxdowuIg==", "dependencies": { - "@smithy/types": "^2.4.0", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -4078,12 +4371,12 @@ } }, "node_modules/@smithy/eventstream-serde-node": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-2.0.12.tgz", - "integrity": "sha512-vf1vMHGOkG3uqN9x1zKOhnvW/XgvhJXWqjV6zZiT2FMjlEayugQ1mzpSqr7uf89+BzjTzuZKERmOsEAmewLbxw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-2.1.3.tgz", + "integrity": "sha512-RPJWWDhj8isk3NtGfm3Xt1WdHyX9ZE42V+m1nLU1I0zZ1hEol/oawHsTnhva/VR5bn+bJ2zscx+BYr0cEPRtmg==", "dependencies": { - "@smithy/eventstream-serde-universal": "^2.0.12", - "@smithy/types": "^2.4.0", + "@smithy/eventstream-serde-universal": "^2.1.3", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -4091,12 +4384,12 @@ } }, "node_modules/@smithy/eventstream-serde-universal": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-2.0.12.tgz", - "integrity": "sha512-xZ3ZNpCxIND+q+UCy7y1n1/5VQEYicgSTNCcPqsKawX+Vd+6OcFX7gUHMyPzL8cZr+GdmJuxNleqHlH4giK2tw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-2.1.3.tgz", + "integrity": "sha512-ssvSMk1LX2jRhiOVgVLGfNJXdB8SvyjieKcJDHq698Gi3LOog6g/+l7ggrN+hZxyjUiDF4cUxgKaZTBUghzhLw==", "dependencies": { - "@smithy/eventstream-codec": "^2.0.12", - "@smithy/types": "^2.4.0", + "@smithy/eventstream-codec": "^2.1.3", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -4104,25 +4397,25 @@ } }, "node_modules/@smithy/fetch-http-handler": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.2.4.tgz", - "integrity": "sha512-gIPRFEGi+c6V52eauGKrjDzPWF2Cu7Z1r5F8A3j2wcwz25sPG/t8kjsbEhli/tS/2zJp/ybCZXe4j4ro3yv/HA==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.4.3.tgz", + "integrity": "sha512-Fn/KYJFo6L5I4YPG8WQb2hOmExgRmNpVH5IK2zU3JKrY5FKW7y9ar5e0BexiIC9DhSKqKX+HeWq/Y18fq7Dkpw==", "dependencies": { - "@smithy/protocol-http": "^3.0.8", - "@smithy/querystring-builder": "^2.0.12", - "@smithy/types": "^2.4.0", - "@smithy/util-base64": "^2.0.0", + "@smithy/protocol-http": "^3.2.1", + "@smithy/querystring-builder": "^2.1.3", + "@smithy/types": "^2.10.1", + "@smithy/util-base64": "^2.1.1", "tslib": "^2.5.0" } }, "node_modules/@smithy/hash-node": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.12.tgz", - "integrity": "sha512-fDZnTr5j9t5qcbeJ037aMZXxMka13Znqwrgy3PAqYj6Dm3XHXHftTH3q+NWgayUxl1992GFtQt1RuEzRMy3NnQ==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.1.3.tgz", + "integrity": "sha512-FsAPCUj7VNJIdHbSxMd5uiZiF20G2zdSDgrgrDrHqIs/VMxK85Vqk5kMVNNDMCZmMezp6UKnac0B4nAyx7HJ9g==", "dependencies": { - "@smithy/types": "^2.4.0", - "@smithy/util-buffer-from": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", + "@smithy/types": "^2.10.1", + "@smithy/util-buffer-from": "^2.1.1", + "@smithy/util-utf8": "^2.1.1", "tslib": "^2.5.0" }, "engines": { @@ -4130,19 +4423,39 @@ } }, "node_modules/@smithy/invalid-dependency": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.12.tgz", - "integrity": "sha512-p5Y+iMHV3SoEpy3VSR7mifbreHQwVSvHSAz/m4GdoXfOzKzaYC8hYv10Ks7Deblkf7lhas8U+lAp9ThbBM+ZXA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.1.3.tgz", + "integrity": "sha512-wkra7d/G4CbngV4xsjYyAYOvdAhahQje/WymuQdVEnXFExJopEu7fbL5AEAlBPgWHXwu94VnCSG00gVzRfExyg==", "dependencies": { - "@smithy/types": "^2.4.0", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" } }, "node_modules/@smithy/is-array-buffer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.0.0.tgz", - "integrity": "sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.1.1.tgz", + "integrity": "sha512-xozSQrcUinPpNPNPds4S7z/FakDTh1MZWtRP/2vQtYB/u3HYrX2UXuZs+VhaKBd6Vc7g2XPr2ZtwGBNDN6fNKQ==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-compression": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@smithy/middleware-compression/-/middleware-compression-2.1.4.tgz", + "integrity": "sha512-euMHyTkvKbndhLvoMKwDDZAcQPhVHv4prkEru2xkbH85ShC8SMLGjuTvQ6UcmOQCzuDZaMCBLhisKxbfn4GWWg==", + "dev": true, "dependencies": { + "@smithy/is-array-buffer": "^2.1.1", + "@smithy/node-config-provider": "^2.2.4", + "@smithy/protocol-http": "^3.2.1", + "@smithy/types": "^2.10.1", + "@smithy/util-config-provider": "^2.2.1", + "@smithy/util-middleware": "^2.1.3", + "@smithy/util-utf8": "^2.1.1", + "fflate": "0.8.1", "tslib": "^2.5.0" }, "engines": { @@ -4150,12 +4463,12 @@ } }, "node_modules/@smithy/middleware-content-length": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.14.tgz", - "integrity": "sha512-poUNgKTw9XwPXfX9nEHpVgrMNVpaSMZbshqvPxFVoalF4wp6kRzYKOfdesSVectlQ51VtigoLfbXcdyPwvxgTg==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.1.3.tgz", + "integrity": "sha512-aJduhkC+dcXxdnv5ZpM3uMmtGmVFKx412R1gbeykS5HXDmRU6oSsyy2SoHENCkfOGKAQOjVE2WVqDJibC0d21g==", "dependencies": { - "@smithy/protocol-http": "^3.0.8", - "@smithy/types": "^2.4.0", + "@smithy/protocol-http": "^3.2.1", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -4163,16 +4476,16 @@ } }, "node_modules/@smithy/middleware-endpoint": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.1.3.tgz", - "integrity": "sha512-ZrQ0/YX6hNVTxqMEHtEaDbDv6pNeEji/a5Vk3HuFC5R3ZY8lfoATyxmOGxBVYnF3NUvZLNC7umEv1WzWGWvCGQ==", - "dependencies": { - "@smithy/middleware-serde": "^2.0.12", - "@smithy/node-config-provider": "^2.1.3", - "@smithy/shared-ini-file-loader": "^2.2.2", - "@smithy/types": "^2.4.0", - "@smithy/url-parser": "^2.0.12", - "@smithy/util-middleware": "^2.0.5", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.4.4.tgz", + "integrity": "sha512-4yjHyHK2Jul4JUDBo2sTsWY9UshYUnXeb/TAK/MTaPEb8XQvDmpwSFnfIRDU45RY1a6iC9LCnmJNg/yHyfxqkw==", + "dependencies": { + "@smithy/middleware-serde": "^2.1.3", + "@smithy/node-config-provider": "^2.2.4", + "@smithy/shared-ini-file-loader": "^2.3.4", + "@smithy/types": "^2.10.1", + "@smithy/url-parser": "^2.1.3", + "@smithy/util-middleware": "^2.1.3", "tslib": "^2.5.0" }, "engines": { @@ -4180,16 +4493,17 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.18.tgz", - "integrity": "sha512-VyrHQRldGSb3v9oFOB5yPxmLT7U2sQic2ytylOnYlnsmVOLlFIaI6sW22c+w2675yq+XZ6HOuzV7x2OBYCWRNA==", - "dependencies": { - "@smithy/node-config-provider": "^2.1.3", - "@smithy/protocol-http": "^3.0.8", - "@smithy/service-error-classification": "^2.0.5", - "@smithy/types": "^2.4.0", - "@smithy/util-middleware": "^2.0.5", - "@smithy/util-retry": "^2.0.5", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.1.4.tgz", + "integrity": "sha512-Cyolv9YckZTPli1EkkaS39UklonxMd08VskiuMhURDjC0HHa/AD6aK/YoD21CHv9s0QLg0WMLvk9YeLTKkXaFQ==", + "dependencies": { + "@smithy/node-config-provider": "^2.2.4", + "@smithy/protocol-http": "^3.2.1", + "@smithy/service-error-classification": "^2.1.3", + "@smithy/smithy-client": "^2.4.2", + "@smithy/types": "^2.10.1", + "@smithy/util-middleware": "^2.1.3", + "@smithy/util-retry": "^2.1.3", "tslib": "^2.5.0", "uuid": "^8.3.2" }, @@ -4198,11 +4512,11 @@ } }, "node_modules/@smithy/middleware-serde": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.12.tgz", - "integrity": "sha512-IBeco157lIScecq2Z+n0gq56i4MTnfKxS7rbfrAORveDJgnbBAaEQgYqMqp/cYqKrpvEXcyTjwKHrBjCCIZh2A==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.1.3.tgz", + "integrity": "sha512-s76LId+TwASrHhUa9QS4k/zeXDUAuNuddKklQzRgumbzge5BftVXHXIqL4wQxKGLocPwfgAOXWx+HdWhQk9hTg==", "dependencies": { - "@smithy/types": "^2.4.0", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -4210,11 +4524,11 @@ } }, "node_modules/@smithy/middleware-stack": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.6.tgz", - "integrity": "sha512-YSvNZeOKWLJ0M/ycxwDIe2Ztkp6Qixmcml1ggsSv2fdHKGkBPhGrX5tMzPGMI1yyx55UEYBi2OB4s+RriXX48A==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.1.3.tgz", + "integrity": "sha512-opMFufVQgvBSld/b7mD7OOEBxF6STyraVr1xel1j0abVILM8ALJvRoFbqSWHGmaDlRGIiV9Q5cGbWi0sdiEaLQ==", "dependencies": { - "@smithy/types": "^2.4.0", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -4222,13 +4536,13 @@ } }, "node_modules/@smithy/node-config-provider": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.1.3.tgz", - "integrity": "sha512-J6lXvRHGVnSX3n1PYi+e1L5HN73DkkJpUviV3Ebf+8wSaIjAf+eVNbzyvh/S5EQz7nf4KVfwbD5vdoZMAthAEQ==", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.2.4.tgz", + "integrity": "sha512-nqazHCp8r4KHSFhRQ+T0VEkeqvA0U+RhehBSr1gunUuNW3X7j0uDrWBxB2gE9eutzy6kE3Y7L+Dov/UXT871vg==", "dependencies": { - "@smithy/property-provider": "^2.0.13", - "@smithy/shared-ini-file-loader": "^2.2.2", - "@smithy/types": "^2.4.0", + "@smithy/property-provider": "^2.1.3", + "@smithy/shared-ini-file-loader": "^2.3.4", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -4236,14 +4550,14 @@ } }, "node_modules/@smithy/node-http-handler": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.1.8.tgz", - "integrity": "sha512-KZylM7Wff/So5SmCiwg2kQNXJ+RXgz34wkxS7WNwIUXuZrZZpY/jKJCK+ZaGyuESDu3TxcaY+zeYGJmnFKbQsA==", - "dependencies": { - "@smithy/abort-controller": "^2.0.12", - "@smithy/protocol-http": "^3.0.8", - "@smithy/querystring-builder": "^2.0.12", - "@smithy/types": "^2.4.0", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.4.1.tgz", + "integrity": "sha512-HCkb94soYhJMxPCa61wGKgmeKpJ3Gftx1XD6bcWEB2wMV1L9/SkQu/6/ysKBnbOzWRE01FGzwrTxucHypZ8rdg==", + "dependencies": { + "@smithy/abort-controller": "^2.1.3", + "@smithy/protocol-http": "^3.2.1", + "@smithy/querystring-builder": "^2.1.3", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -4251,11 +4565,11 @@ } }, "node_modules/@smithy/property-provider": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.13.tgz", - "integrity": "sha512-VJqUf2CbsQX6uUiC5dUPuoEATuFjkbkW3lJHbRnpk9EDC9X+iKqhfTK+WP+lve5EQ9TcCI1Q6R7hrg41FyC54w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.1.3.tgz", + "integrity": "sha512-bMz3se+ySKWNrgm7eIiQMa2HO/0fl2D0HvLAdg9pTMcpgp4SqOAh6bz7Ik6y7uQqSrk4rLjIKgbQ6yzYgGehCQ==", "dependencies": { - "@smithy/types": "^2.4.0", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -4263,11 +4577,11 @@ } }, "node_modules/@smithy/protocol-http": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.0.8.tgz", - "integrity": "sha512-SHJvYeWq8q0FK8xHk+xjV9dzDUDjFMT+G1pZbV+XB6OVoac/FSVshlMNPeUJ8AmSkcDKHRu5vASnRqZHgD3qhw==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.2.1.tgz", + "integrity": "sha512-KLrQkEw4yJCeAmAH7hctE8g9KwA7+H2nSJwxgwIxchbp/L0B5exTdOQi9D5HinPLlothoervGmhpYKelZ6AxIA==", "dependencies": { - "@smithy/types": "^2.4.0", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -4275,12 +4589,12 @@ } }, "node_modules/@smithy/querystring-builder": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.12.tgz", - "integrity": "sha512-cDbF07IuCjiN8CdGvPzfJjXIrmDSelScRfyJYrYBNBbKl2+k7QD/KqiHhtRyEKgID5mmEVrV6KE6L/iPJ98sFw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.1.3.tgz", + "integrity": "sha512-kFD3PnNqKELe6m9GRHQw/ftFFSZpnSeQD4qvgDB6BQN6hREHELSosVFUMPN4M3MDKN2jAwk35vXHLoDrNfKu0A==", "dependencies": { - "@smithy/types": "^2.4.0", - "@smithy/util-uri-escape": "^2.0.0", + "@smithy/types": "^2.10.1", + "@smithy/util-uri-escape": "^2.1.1", "tslib": "^2.5.0" }, "engines": { @@ -4288,11 +4602,11 @@ } }, "node_modules/@smithy/querystring-parser": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.12.tgz", - "integrity": "sha512-fytyTcXaMzPBuNtPlhj5v6dbl4bJAnwKZFyyItAGt4Tgm9HFPZNo7a9r1SKPr/qdxUEBzvL9Rh+B9SkTX3kFxg==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.1.3.tgz", + "integrity": "sha512-3+CWJoAqcBMR+yvz6D+Fc5VdoGFtfenW6wqSWATWajrRMGVwJGPT3Vy2eb2bnMktJc4HU4bpjeovFa566P3knQ==", "dependencies": { - "@smithy/types": "^2.4.0", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -4300,22 +4614,22 @@ } }, "node_modules/@smithy/service-error-classification": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.5.tgz", - "integrity": "sha512-M0SeJnEgD2ywJyV99Fb1yKFzmxDe9JfpJiYTVSRMyRLc467BPU0qsuuDPzMCdB1mU8M8u1rVOdkqdoyFN8UFTw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.1.3.tgz", + "integrity": "sha512-iUrpSsem97bbXHHT/v3s7vaq8IIeMo6P6cXdeYHrx0wOJpMeBGQF7CB0mbJSiTm3//iq3L55JiEm8rA7CTVI8A==", "dependencies": { - "@smithy/types": "^2.4.0" + "@smithy/types": "^2.10.1" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@smithy/shared-ini-file-loader": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.2.2.tgz", - "integrity": "sha512-noyQUPn7b1M8uB0GEXc/Zyxq+5K2b7aaqWnLp+hgJ7+xu/FCvtyWy5eWLDjQEsHnAet2IZhS5QF8872OR69uNg==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.3.4.tgz", + "integrity": "sha512-CiZmPg9GeDKbKmJGEFvJBsJcFnh0AQRzOtQAzj1XEa8N/0/uSN/v1LYzgO7ry8hhO8+9KB7+DhSW0weqBra4Aw==", "dependencies": { - "@smithy/types": "^2.4.0", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -4323,17 +4637,17 @@ } }, "node_modules/@smithy/signature-v4": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.9.tgz", - "integrity": "sha512-RkHP0joSI1j2EI+mU55sOi33/aMMkKdL9ZY+SWrPxsiCe1oyzzuy79Tpn8X7uT+t0ilNmQlwPpkP/jUy940pEA==", - "dependencies": { - "@smithy/eventstream-codec": "^2.0.9", - "@smithy/is-array-buffer": "^2.0.0", - "@smithy/types": "^2.3.3", - "@smithy/util-hex-encoding": "^2.0.0", - "@smithy/util-middleware": "^2.0.2", - "@smithy/util-uri-escape": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.1.3.tgz", + "integrity": "sha512-Jq4iPPdCmJojZTsPePn4r1ULShh6ONkokLuxp1Lnk4Sq7r7rJp4HlA1LbPBq4bD64TIzQezIpr1X+eh5NYkNxw==", + "dependencies": { + "@smithy/eventstream-codec": "^2.1.3", + "@smithy/is-array-buffer": "^2.1.1", + "@smithy/types": "^2.10.1", + "@smithy/util-hex-encoding": "^2.1.1", + "@smithy/util-middleware": "^2.1.3", + "@smithy/util-uri-escape": "^2.1.1", + "@smithy/util-utf8": "^2.1.1", "tslib": "^2.5.0" }, "engines": { @@ -4341,13 +4655,15 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "2.1.12", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.1.12.tgz", - "integrity": "sha512-XXqhridfkKnpj+lt8vM6HRlZbqUAqBjVC74JIi13F/AYQd/zTj9SOyGfxnbp4mjY9q28LityxIuV8CTinr9r5w==", - "dependencies": { - "@smithy/middleware-stack": "^2.0.6", - "@smithy/types": "^2.4.0", - "@smithy/util-stream": "^2.0.17", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.4.2.tgz", + "integrity": "sha512-ntAFYN51zu3N3mCd95YFcFi/8rmvm//uX+HnK24CRbI6k5Rjackn0JhgKz5zOx/tbNvOpgQIwhSX+1EvEsBLbA==", + "dependencies": { + "@smithy/middleware-endpoint": "^2.4.4", + "@smithy/middleware-stack": "^2.1.3", + "@smithy/protocol-http": "^3.2.1", + "@smithy/types": "^2.10.1", + "@smithy/util-stream": "^2.1.3", "tslib": "^2.5.0" }, "engines": { @@ -4355,9 +4671,9 @@ } }, "node_modules/@smithy/types": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.4.0.tgz", - "integrity": "sha512-iH1Xz68FWlmBJ9vvYeHifVMWJf82ONx+OybPW8ZGf5wnEv2S0UXcU4zwlwJkRXuLKpcSLHrraHbn2ucdVXLb4g==", + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.10.1.tgz", + "integrity": "sha512-hjQO+4ru4cQ58FluQvKKiyMsFg0A6iRpGm2kqdH8fniyNd2WyanoOsYJfMX/IFLuLxEoW6gnRkNZy1y6fUUhtA==", "dependencies": { "tslib": "^2.5.0" }, @@ -4366,21 +4682,21 @@ } }, "node_modules/@smithy/url-parser": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.12.tgz", - "integrity": "sha512-qgkW2mZqRvlNUcBkxYB/gYacRaAdck77Dk3/g2iw0S9F0EYthIS3loGfly8AwoWpIvHKhkTsCXXQfzksgZ4zIA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.1.3.tgz", + "integrity": "sha512-X1NRA4WzK/ihgyzTpeGvI9Wn45y8HmqF4AZ/FazwAv8V203Ex+4lXqcYI70naX9ETqbqKVzFk88W6WJJzCggTQ==", "dependencies": { - "@smithy/querystring-parser": "^2.0.12", - "@smithy/types": "^2.4.0", + "@smithy/querystring-parser": "^2.1.3", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" } }, "node_modules/@smithy/util-base64": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.0.0.tgz", - "integrity": "sha512-Zb1E4xx+m5Lud8bbeYi5FkcMJMnn+1WUnJF3qD7rAdXpaL7UjkFQLdmW5fHadoKbdHpwH9vSR8EyTJFHJs++tA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.1.1.tgz", + "integrity": "sha512-UfHVpY7qfF/MrgndI5PexSKVTxSZIdz9InghTFa49QOvuu9I52zLPLUHXvHpNuMb1iD2vmc6R+zbv/bdMipR/g==", "dependencies": { - "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-buffer-from": "^2.1.1", "tslib": "^2.5.0" }, "engines": { @@ -4388,17 +4704,17 @@ } }, "node_modules/@smithy/util-body-length-browser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.0.0.tgz", - "integrity": "sha512-JdDuS4ircJt+FDnaQj88TzZY3+njZ6O+D3uakS32f2VNnDo3vyEuNdBOh/oFd8Df1zSZOuH1HEChk2AOYDezZg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.1.1.tgz", + "integrity": "sha512-ekOGBLvs1VS2d1zM2ER4JEeBWAvIOUKeaFch29UjjJsxmZ/f0L3K3x0dEETgh3Q9bkZNHgT+rkdl/J/VUqSRag==", "dependencies": { "tslib": "^2.5.0" } }, "node_modules/@smithy/util-body-length-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.1.0.tgz", - "integrity": "sha512-/li0/kj/y3fQ3vyzn36NTLGmUwAICb7Jbe/CsWCktW363gh1MOcpEcSO3mJ344Gv2dqz8YJCLQpb6hju/0qOWw==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.2.1.tgz", + "integrity": "sha512-/ggJG+ta3IDtpNVq4ktmEUtOkH1LW64RHB5B0hcr5ZaWBmo96UX2cIOVbjCqqDickTXqBWZ4ZO0APuaPrD7Abg==", "dependencies": { "tslib": "^2.5.0" }, @@ -4407,11 +4723,11 @@ } }, "node_modules/@smithy/util-buffer-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.0.0.tgz", - "integrity": "sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.1.1.tgz", + "integrity": "sha512-clhNjbyfqIv9Md2Mg6FffGVrJxw7bgK7s3Iax36xnfVj6cg0fUG7I4RH0XgXJF8bxi+saY5HR21g2UPKSxVCXg==", "dependencies": { - "@smithy/is-array-buffer": "^2.0.0", + "@smithy/is-array-buffer": "^2.1.1", "tslib": "^2.5.0" }, "engines": { @@ -4419,9 +4735,9 @@ } }, "node_modules/@smithy/util-config-provider": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.0.0.tgz", - "integrity": "sha512-xCQ6UapcIWKxXHEU4Mcs2s7LcFQRiU3XEluM2WcCjjBtQkUN71Tb+ydGmJFPxMUrW/GWMgQEEGipLym4XG0jZg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.2.1.tgz", + "integrity": "sha512-50VL/tx9oYYcjJn/qKqNy7sCtpD0+s8XEBamIFo4mFFTclKMNp+rsnymD796uybjiIquB7VCB/DeafduL0y2kw==", "dependencies": { "tslib": "^2.5.0" }, @@ -4430,13 +4746,13 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.16.tgz", - "integrity": "sha512-Uv5Cu8nVkuvLn0puX+R9zWbSNpLIR3AxUlPoLJ7hC5lvir8B2WVqVEkJLwtixKAncVLasnTVjPDCidtAUTGEQw==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.1.4.tgz", + "integrity": "sha512-J6XAVY+/g7jf03QMnvqPyU+8jqGrrtXoKWFVOS+n1sz0Lg8HjHJ1ANqaDN+KTTKZRZlvG8nU5ZrJOUL6VdwgcQ==", "dependencies": { - "@smithy/property-provider": "^2.0.13", - "@smithy/smithy-client": "^2.1.12", - "@smithy/types": "^2.4.0", + "@smithy/property-provider": "^2.1.3", + "@smithy/smithy-client": "^2.4.2", + "@smithy/types": "^2.10.1", "bowser": "^2.11.0", "tslib": "^2.5.0" }, @@ -4445,16 +4761,16 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "2.0.21", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.21.tgz", - "integrity": "sha512-cUEsttVZ79B7Al2rWK2FW03HBpD9LyuqFtm+1qFty5u9sHSdesr215gS2Ln53fTopNiPgeXpdoM3IgjvIO0rJw==", - "dependencies": { - "@smithy/config-resolver": "^2.0.16", - "@smithy/credential-provider-imds": "^2.0.18", - "@smithy/node-config-provider": "^2.1.3", - "@smithy/property-provider": "^2.0.13", - "@smithy/smithy-client": "^2.1.12", - "@smithy/types": "^2.4.0", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.2.3.tgz", + "integrity": "sha512-ttUISrv1uVOjTlDa3nznX33f0pthoUlP+4grhTvOzcLhzArx8qHB94/untGACOG3nlf8vU20nI2iWImfzoLkYA==", + "dependencies": { + "@smithy/config-resolver": "^2.1.4", + "@smithy/credential-provider-imds": "^2.2.4", + "@smithy/node-config-provider": "^2.2.4", + "@smithy/property-provider": "^2.1.3", + "@smithy/smithy-client": "^2.4.2", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -4462,12 +4778,12 @@ } }, "node_modules/@smithy/util-endpoints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-1.0.2.tgz", - "integrity": "sha512-QEdq+sP68IJHAMVB2ugKVVZEWeKQtZLuf+akHzc8eTVElsZ2ZdVLWC6Cp+uKjJ/t4yOj1qu6ZzyxJQEQ8jdEjg==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-1.1.4.tgz", + "integrity": "sha512-/qAeHmK5l4yQ4/bCIJ9p49wDe9rwWtOzhPHblu386fwPNT3pxmodgcs9jDCV52yK9b4rB8o9Sj31P/7Vzka1cg==", "dependencies": { - "@smithy/node-config-provider": "^2.1.3", - "@smithy/types": "^2.4.0", + "@smithy/node-config-provider": "^2.2.4", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -4475,9 +4791,9 @@ } }, "node_modules/@smithy/util-hex-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.0.0.tgz", - "integrity": "sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.1.1.tgz", + "integrity": "sha512-3UNdP2pkYUUBGEXzQI9ODTDK+Tcu1BlCyDBaRHwyxhA+8xLP8agEKQq4MGmpjqb4VQAjq9TwlCQX0kP6XDKYLg==", "dependencies": { "tslib": "^2.5.0" }, @@ -4486,11 +4802,11 @@ } }, "node_modules/@smithy/util-middleware": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.5.tgz", - "integrity": "sha512-1lyT3TcaMJQe+OFfVI+TlomDkPuVzb27NZYdYtmSTltVmLaUjdCyt4KE+OH1CnhZKsz4/cdCL420Lg9UH5Z2Mw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.1.3.tgz", + "integrity": "sha512-/+2fm7AZ2ozl5h8wM++ZP0ovE9/tiUUAHIbCfGfb3Zd3+Dyk17WODPKXBeJ/TnK5U+x743QmA0xHzlSm8I/qhw==", "dependencies": { - "@smithy/types": "^2.4.0", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -4498,12 +4814,12 @@ } }, "node_modules/@smithy/util-retry": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.5.tgz", - "integrity": "sha512-x3t1+MQAJ6QONk3GTbJNcugCFDVJ+Bkro5YqQQK1EyVesajNDqxFtCx9WdOFNGm/Cbm7tUdwVEmfKQOJoU2Vtw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.1.3.tgz", + "integrity": "sha512-Kbvd+GEMuozbNUU3B89mb99tbufwREcyx2BOX0X2+qHjq6Gvsah8xSDDgxISDwcOHoDqUWO425F0Uc/QIRhYkg==", "dependencies": { - "@smithy/service-error-classification": "^2.0.5", - "@smithy/types": "^2.4.0", + "@smithy/service-error-classification": "^2.1.3", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -4511,17 +4827,17 @@ } }, "node_modules/@smithy/util-stream": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.17.tgz", - "integrity": "sha512-fP/ZQ27rRvHsqItds8yB7jerwMpZFTL3QqbQbidUiG0+mttMoKdP0ZqnvM8UK5q0/dfc3/pN7g4XKPXOU7oRWw==", - "dependencies": { - "@smithy/fetch-http-handler": "^2.2.4", - "@smithy/node-http-handler": "^2.1.8", - "@smithy/types": "^2.4.0", - "@smithy/util-base64": "^2.0.0", - "@smithy/util-buffer-from": "^2.0.0", - "@smithy/util-hex-encoding": "^2.0.0", - "@smithy/util-utf8": "^2.0.0", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.1.3.tgz", + "integrity": "sha512-HvpEQbP8raTy9n86ZfXiAkf3ezp1c3qeeO//zGqwZdrfaoOpGKQgF2Sv1IqZp7wjhna7pvczWaGUHjcOPuQwKw==", + "dependencies": { + "@smithy/fetch-http-handler": "^2.4.3", + "@smithy/node-http-handler": "^2.4.1", + "@smithy/types": "^2.10.1", + "@smithy/util-base64": "^2.1.1", + "@smithy/util-buffer-from": "^2.1.1", + "@smithy/util-hex-encoding": "^2.1.1", + "@smithy/util-utf8": "^2.1.1", "tslib": "^2.5.0" }, "engines": { @@ -4529,9 +4845,9 @@ } }, "node_modules/@smithy/util-uri-escape": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.0.0.tgz", - "integrity": "sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.1.1.tgz", + "integrity": "sha512-saVzI1h6iRBUVSqtnlOnc9ssU09ypo7n+shdQ8hBTZno/9rZ3AuRYvoHInV57VF7Qn7B+pFJG7qTzFiHxWlWBw==", "dependencies": { "tslib": "^2.5.0" }, @@ -4540,11 +4856,11 @@ } }, "node_modules/@smithy/util-utf8": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.0.0.tgz", - "integrity": "sha512-rctU1VkziY84n5OXe3bPNpKR001ZCME2JCaBBFgtiM2hfKbHFudc/BkMuPab8hRbLd0j3vbnBTTZ1igBf0wgiQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.1.1.tgz", + "integrity": "sha512-BqTpzYEcUMDwAKr7/mVRUtHDhs6ZoXDi9NypMvMfOr/+u1NW7JgqodPDECiiLboEm6bobcPcECxzjtQh865e9A==", "dependencies": { - "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-buffer-from": "^2.1.1", "tslib": "^2.5.0" }, "engines": { @@ -4552,12 +4868,12 @@ } }, "node_modules/@smithy/util-waiter": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-2.0.12.tgz", - "integrity": "sha512-3sENmyVa1NnOPoiT2NCApPmu7ukP7S/v7kL9IxNmnygkDldn7/yK0TP42oPJLwB2k3mospNsSePIlqdXEUyPHA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-2.1.3.tgz", + "integrity": "sha512-3R0wNFAQQoH9e4m+bVLDYNOst2qNxtxFgq03WoNHWTBOqQT3jFnOBRj1W51Rf563xDA5kwqjziksxn6RKkHB+Q==", "dependencies": { - "@smithy/abort-controller": "^2.0.12", - "@smithy/types": "^2.4.0", + "@smithy/abort-controller": "^2.1.3", + "@smithy/types": "^2.10.1", "tslib": "^2.5.0" }, "engines": { @@ -4619,40 +4935,16 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/@tufjs/models/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@tufjs/models/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@types/aws-lambda": { - "version": "8.10.122", - "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.122.tgz", - "integrity": "sha512-vBkIh9AY22kVOCEKo5CJlyCgmSWvasC+SWUxL/x/vOwRobMpI/HG1xp/Ae3AqmSiZeLUbOhW0FCD3ZjqqUxmXw==", + "version": "8.10.136", + "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.136.tgz", + "integrity": "sha512-cmmgqxdVGhxYK9lZMYYXYRJk6twBo53ivtXjIUEFZxfxe4TkZTZBK3RRWrY2HjJcUIix0mdifn15yjOAat5lTA==", "dev": true }, "node_modules/@types/babel__core": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.2.tgz", - "integrity": "sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, "dependencies": { "@babel/parser": "^7.20.7", @@ -4663,18 +4955,18 @@ } }, "node_modules/@types/babel__generator": { - "version": "7.6.5", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.5.tgz", - "integrity": "sha512-h9yIuWbJKdOPLJTbmSpPzkF67e659PbQDba7ifWm5BJ8xTv+sDmS7rFmywkWOvXedGTivCdeGSIIX8WLcRTz8w==", + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", "dev": true, "dependencies": { "@babel/types": "^7.0.0" } }, "node_modules/@types/babel__template": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.2.tgz", - "integrity": "sha512-/AVzPICMhMOMYoSx9MoKpGDKdBRsIXMNByh1PXSZoa+v6ZoLa8xxtsT/uLQ/NJm0XVAWl/BvId4MlDeXJaeIZQ==", + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, "dependencies": { "@babel/parser": "^7.1.0", @@ -4682,59 +4974,59 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.2.tgz", - "integrity": "sha512-ojlGK1Hsfce93J0+kn3H5R73elidKUaZonirN33GSmgTUMpzI/MIFfSpF3haANe3G1bEBS9/9/QEqwTzwqFsKw==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", + "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", "dev": true, "dependencies": { "@babel/types": "^7.20.7" } }, "node_modules/@types/cls-hooked": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/@types/cls-hooked/-/cls-hooked-4.3.6.tgz", - "integrity": "sha512-Ys46tagI3aFwFizHYwG2v0oS+mMfp1nubY2ETU/RY/D0jLOXpqqVEItjhOmKMI8SklF3MI4Y7oSp9UFkBk4CXQ==", + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/@types/cls-hooked/-/cls-hooked-4.3.8.tgz", + "integrity": "sha512-tf/7H883gFA6MPlWI15EQtfNZ+oPL0gLKkOlx9UHFrun1fC/FkuyNBpTKq1B5E3T4fbvjId6WifHUdSGsMMuPg==", "dependencies": { "@types/node": "*" } }, "node_modules/@types/graceful-fs": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.7.tgz", - "integrity": "sha512-MhzcwU8aUygZroVwL2jeYk6JisJrPl/oov/gsgGCue9mkgl9wjGbzReYQClxiUgFDnib9FuHqTndccKeZKxTRw==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", "dev": true }, "node_modules/@types/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-gPQuzaPR5h/djlAv2apEG1HVOyj1IUs7GpfMZixU0/0KXT3pm64ylHuMUI1/Akh+sq/iikxg6Z2j+fcMDXaaTQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "node_modules/@types/istanbul-reports": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.2.tgz", - "integrity": "sha512-kv43F9eb3Lhj+lr/Hn6OcLCs/sSM8bt+fIaP11rCYngfV6NVjzWXJ17owQtDQTL9tQ8WSLUrGsSJ6rJz0F1w1A==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", "dev": true, "dependencies": { "@types/istanbul-lib-report": "*" } }, "node_modules/@types/jest": { - "version": "29.5.5", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.5.tgz", - "integrity": "sha512-ebylz2hnsWR9mYvmBFbXJXr+33UPc4+ZdxyDXh5w0FlPBTfCVN3wPL+kuOiQt3xvrK419v7XWeAs+AeOksafXg==", + "version": "29.5.12", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", + "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -4742,15 +5034,15 @@ } }, "node_modules/@types/jmespath": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@types/jmespath/-/jmespath-0.15.0.tgz", - "integrity": "sha512-uaht4XcYSq5ZrPriQW8C+g5DhptewRd1E84ph7L167sCyzLObz+U3JTpmYq/CNkvjNsz2mtyQoHPNEYQYTzWmg==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@types/jmespath/-/jmespath-0.15.2.tgz", + "integrity": "sha512-pegh49FtNsC389Flyo9y8AfkVIZn9MMPE9yJrO9svhq6Fks2MwymULWjZqySuxmctd3ZH4/n7Mr98D+1Qo5vGA==", "dev": true }, "node_modules/@types/json-schema": { - "version": "7.0.13", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.13.tgz", - "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==", + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, "node_modules/@types/json5": { @@ -4760,15 +5052,15 @@ "dev": true }, "node_modules/@types/lodash": { - "version": "4.14.199", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.199.tgz", - "integrity": "sha512-Vrjz5N5Ia4SEzWWgIVwnHNEnb1UE1XMkvY5DGXrAeOGE9imk0hgTHh5GyDjLDJi9OTCn9oo9dXH1uToK1VRfrg==", + "version": "4.14.202", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.202.tgz", + "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==", "dev": true }, "node_modules/@types/lodash.merge": { - "version": "4.6.7", - "resolved": "https://registry.npmjs.org/@types/lodash.merge/-/lodash.merge-4.6.7.tgz", - "integrity": "sha512-OwxUJ9E50gw3LnAefSHJPHaBLGEKmQBQ7CZe/xflHkyy/wH2zVyEIAKReHvVrrn7zKdF58p16We9kMfh7v0RRQ==", + "version": "4.6.9", + "resolved": "https://registry.npmjs.org/@types/lodash.merge/-/lodash.merge-4.6.9.tgz", + "integrity": "sha512-23sHDPmzd59kUgWyKGiOMO2Qb9YtqRO/x4IhkgNUiPQ1+5MUVqi6bCZeq9nBJ17msjIMbEIO5u+XW4Kz6aGUhQ==", "dev": true, "dependencies": { "@types/lodash": "*" @@ -4781,96 +5073,93 @@ "dev": true }, "node_modules/@types/minimist": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.3.tgz", - "integrity": "sha512-ZYFzrvyWUNhaPomn80dsMNgMeXxNWZBdkuG/hWlUvXvbdUH8ZERNBGXnU87McuGcWDsyzX2aChCv/SVN348k3A==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", "dev": true }, "node_modules/@types/node": { - "version": "20.7.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.7.1.tgz", - "integrity": "sha512-LT+OIXpp2kj4E2S/p91BMe+VgGX2+lfO+XTpfXhh+bCk2LkQtHZSub8ewFBMGP5ClysPjTDFa4sMI8Q3n4T0wg==" + "version": "20.11.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.24.tgz", + "integrity": "sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==", + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/normalize-package-data": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.2.tgz", - "integrity": "sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==", + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", "dev": true }, "node_modules/@types/promise-retry": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@types/promise-retry/-/promise-retry-1.1.4.tgz", - "integrity": "sha512-DmJeCIhfpAE0XonyVUa0BRLbkE/97L9KUO8iM2br8Bzl8GLuru842K1A8VgKJwNjtLvIbUnSqElhNKdM9mGl9w==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@types/promise-retry/-/promise-retry-1.1.6.tgz", + "integrity": "sha512-EC1+OMXV0PZb0pf+cmyxc43MEP2CDumZe4AfuxWboxxEixztIebknpJPZAX5XlodGF1OY+C1E/RAeNGzxf+bJA==", "dev": true, "dependencies": { "@types/retry": "*" } }, "node_modules/@types/retry": { - "version": "0.12.3", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.3.tgz", - "integrity": "sha512-rkxEZUFIyDEZhC6EfHz6Hwos2zXewCOLBzhdgv7D55qu4OAySNwDZzxbaMpFI6XthdBa5oHhR5s6/9MSuTfw4g==", + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.5.tgz", + "integrity": "sha512-3xSjTp3v03X/lSQLkczaN9UIEwJMoMCA1+Nb5HfbJEQWogdeQIyVtTvxPXDQjZ5zws8rFQfVfRdz03ARihPJgw==", "dev": true }, "node_modules/@types/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-OxepLK9EuNEIPxWNME+C6WwbRAOOI2o2BaQEGzz5Lu2e4Z5eDnEo+/aVEDMIXywoJitJ7xWd641wrGLZdtwRyw==", + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", "dev": true }, "node_modules/@types/sinon": { - "version": "10.0.17", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.17.tgz", - "integrity": "sha512-+6ILpcixQ0Ma3dHMTLv4rSycbDXkDljgKL+E0nI2RUxxhYTFyPSjt6RVMxh7jUshvyVcBvicb0Ktj+lAJcjgeA==", + "version": "10.0.20", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.20.tgz", + "integrity": "sha512-2APKKruFNCAZgx3daAyACGzWuJ028VVCUDk6o2rw/Z4PXT0ogwdV4KUegW0MwVs0Zu59auPXbbuBJHF12Sx1Eg==", "dev": true, "dependencies": { "@types/sinonjs__fake-timers": "*" } }, "node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.3.tgz", - "integrity": "sha512-4g+2YyWe0Ve+LBh+WUm1697PD0Kdi6coG1eU0YjQbwx61AZ8XbEpL1zIT6WjuUKrCMCROpEaYQPDjBnDouBVAQ==", + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", + "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", "dev": true }, "node_modules/@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", - "dev": true - }, - "node_modules/@types/uuid": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.4.tgz", - "integrity": "sha512-zAuJWQflfx6dYJM62vna+Sn5aeSWhh3OB+wfUEACNcqUSc0AGc5JKl+ycL1vrH7frGTXhJchYjE1Hak8L819dA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", "dev": true }, "node_modules/@types/yargs": { - "version": "17.0.25", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.25.tgz", - "integrity": "sha512-gy7iPgwnzNvxgAEi2bXOHWCVOG6f7xsprVJH4MjlAWeBmJ7vh/Y1kwMtUrs64ztf24zVIRCpr3n/z6gm9QIkgg==", + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", "dev": true, "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { - "version": "21.0.1", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.1.tgz", - "integrity": "sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ==", + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.3.tgz", - "integrity": "sha512-vntq452UHNltxsaaN+L9WyuMch8bMd9CqJ3zhzTPXXidwbf5mqqKCVXEuvRZUqLJSTLeWE65lQwyXsRGnXkCTA==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.7.3", - "@typescript-eslint/type-utils": "6.7.3", - "@typescript-eslint/utils": "6.7.3", - "@typescript-eslint/visitor-keys": "6.7.3", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -4896,15 +5185,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.7.3.tgz", - "integrity": "sha512-TlutE+iep2o7R8Lf+yoer3zU6/0EAUc8QIBB3GYBc1KGz4c4TRm83xwXUZVPlZ6YCLss4r77jbu6j3sendJoiQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.7.3", - "@typescript-eslint/types": "6.7.3", - "@typescript-eslint/typescript-estree": "6.7.3", - "@typescript-eslint/visitor-keys": "6.7.3", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4" }, "engines": { @@ -4924,13 +5213,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.7.3.tgz", - "integrity": "sha512-wOlo0QnEou9cHO2TdkJmzF7DFGvAKEnB82PuPNHpT8ZKKaZu6Bm63ugOTn9fXNJtvuDPanBc78lGUGGytJoVzQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.3", - "@typescript-eslint/visitor-keys": "6.7.3" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -4941,13 +5230,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.7.3.tgz", - "integrity": "sha512-Fc68K0aTDrKIBvLnKTZ5Pf3MXK495YErrbHb1R6aTpfK5OdSFj0rVN7ib6Tx6ePrZ2gsjLqr0s98NG7l96KSQw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.7.3", - "@typescript-eslint/utils": "6.7.3", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -4968,9 +5257,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.7.3.tgz", - "integrity": "sha512-4g+de6roB2NFcfkZb439tigpAMnvEIg3rIjWQ+EM7IBaYt/CdJt6em9BJ4h4UpdgaBWdmx2iWsafHTrqmgIPNw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -4981,16 +5270,17 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.3.tgz", - "integrity": "sha512-YLQ3tJoS4VxLFYHTw21oe1/vIZPRqAO91z6Uv0Ss2BKm/Ag7/RVQBcXTGcXhgJMdA4U+HrKuY5gWlJlvoaKZ5g==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.3", - "@typescript-eslint/visitor-keys": "6.7.3", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", + "minimatch": "9.0.3", "semver": "^7.5.4", "ts-api-utils": "^1.0.1" }, @@ -5008,17 +5298,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.7.3.tgz", - "integrity": "sha512-vzLkVder21GpWRrmSR9JxGZ5+ibIUSudXlW52qeKpzUEQhRSmyZiVDDj3crAth7+5tmN1ulvgKaCU2f/bPRCzg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.7.3", - "@typescript-eslint/types": "6.7.3", - "@typescript-eslint/typescript-estree": "6.7.3", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", "semver": "^7.5.4" }, "engines": { @@ -5033,12 +5323,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.3.tgz", - "integrity": "sha512-HEVXkU9IB+nk9o63CeICMHxFWbHWr3E1mpilIQBe9+7L/lH97rleFLVtYsfnWB+JVMaiFnEaxvknvmIzX+CqVg==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.7.3", + "@typescript-eslint/types": "6.21.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -5049,6 +5339,12 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "node_modules/@yarnpkg/lockfile": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", @@ -5103,15 +5399,18 @@ } }, "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -5130,9 +5429,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", "dev": true, "engines": { "node": ">=0.4.0" @@ -5449,9 +5748,9 @@ } }, "node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", "dev": true }, "node_modules/async-hook-jl": { @@ -5489,9 +5788,9 @@ } }, "node_modules/aws-cdk": { - "version": "2.98.0", - "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.98.0.tgz", - "integrity": "sha512-K8WCstCTmJo7dOwzAfUxhWmRYs9FmtFMpKh0OkEOs7iJ1HsNvAOz2LUURkVMqINXgfhmqqjgK6PQxI4AfgOdGA==", + "version": "2.131.0", + "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.131.0.tgz", + "integrity": "sha512-ji+MwGFGC88HE/EqV6/VARBp5mu3nXIDa/GYwtGycJqu6WqXhNZXWeDH0JsWaY6+BSUdpY6pr6KWpV+MDyVkDg==", "bin": { "cdk": "bin/cdk" }, @@ -5503,9 +5802,9 @@ } }, "node_modules/aws-cdk-lib": { - "version": "2.98.0", - "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.98.0.tgz", - "integrity": "sha512-6APM6zVTCi59L/8lPX47DINlCD9ZG7OEQ28pD/ftmHZ8qC7AlBWwWqOfuSL+DyEbJBLcw3AZ2MLM1AMJPO+sVg==", + "version": "2.131.0", + "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.131.0.tgz", + "integrity": "sha512-9XLgiTgY+q0S3K93VPeJO0chIN8BZwZ3aSrILvF868Dz+0NTNrD2m5M0xGK5Rw0uoJS+N+DvGaz/2hLAiVqcBw==", "bundleDependencies": [ "@balena/dockerignore", "case", @@ -5516,20 +5815,22 @@ "punycode", "semver", "table", - "yaml" + "yaml", + "mime-types" ], "dependencies": { - "@aws-cdk/asset-awscli-v1": "^2.2.200", + "@aws-cdk/asset-awscli-v1": "^2.2.202", "@aws-cdk/asset-kubectl-v20": "^2.1.2", "@aws-cdk/asset-node-proxy-agent-v6": "^2.0.1", "@balena/dockerignore": "^1.0.2", "case": "1.6.3", - "fs-extra": "^11.1.1", - "ignore": "^5.2.4", + "fs-extra": "^11.2.0", + "ignore": "^5.3.1", "jsonschema": "^1.4.1", + "mime-types": "^2.1.35", "minimatch": "^3.1.2", - "punycode": "^2.3.0", - "semver": "^7.5.4", + "punycode": "^2.3.1", + "semver": "^7.6.0", "table": "^6.8.1", "yaml": "1.10.2" }, @@ -5644,7 +5945,7 @@ "license": "MIT" }, "node_modules/aws-cdk-lib/node_modules/fs-extra": { - "version": "11.1.1", + "version": "11.2.0", "inBundle": true, "license": "MIT", "dependencies": { @@ -5662,7 +5963,7 @@ "license": "ISC" }, "node_modules/aws-cdk-lib/node_modules/ignore": { - "version": "5.2.4", + "version": "5.3.1", "inBundle": true, "license": "MIT", "engines": { @@ -5717,8 +6018,27 @@ "node": ">=10" } }, - "node_modules/aws-cdk-lib/node_modules/minimatch": { - "version": "3.1.2", + "node_modules/aws-cdk-lib/node_modules/mime-db": { + "version": "1.52.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/aws-cdk-lib/node_modules/mime-types": { + "version": "2.1.35", + "inBundle": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/aws-cdk-lib/node_modules/minimatch": { + "version": "3.1.2", "inBundle": true, "license": "ISC", "dependencies": { @@ -5729,7 +6049,7 @@ } }, "node_modules/aws-cdk-lib/node_modules/punycode": { - "version": "2.3.0", + "version": "2.3.1", "inBundle": true, "license": "MIT", "engines": { @@ -5745,7 +6065,7 @@ } }, "node_modules/aws-cdk-lib/node_modules/semver": { - "version": "7.5.4", + "version": "7.6.0", "inBundle": true, "license": "ISC", "dependencies": { @@ -5814,7 +6134,7 @@ } }, "node_modules/aws-cdk-lib/node_modules/universalify": { - "version": "2.0.0", + "version": "2.0.1", "inBundle": true, "license": "MIT", "engines": { @@ -5843,9 +6163,9 @@ } }, "node_modules/aws-sdk": { - "version": "2.1484.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1484.0.tgz", - "integrity": "sha512-emfCmb5j/UtaB7U8tvLpGdVNAlZMg4xZOhoFvL8jBQwIVJyCRyaqcshe31JXTwJdafThn2pNPtQOeYbZJCE0Ow==", + "version": "2.1568.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1568.0.tgz", + "integrity": "sha512-ECGJlhn4tnvC+MwNxGDGbhKEOwqLtmtEb3VK5s0z8pcU60Uv1b8+wRPKjqM/eJ+J4N5CL92Y5aq5xAdTquBZRQ==", "dev": true, "dependencies": { "buffer": "4.9.2", @@ -5857,34 +6177,34 @@ "url": "0.10.3", "util": "^0.12.4", "uuid": "8.0.0", - "xml2js": "0.5.0" + "xml2js": "0.6.2" }, "engines": { "node": ">= 10.0.0" } }, "node_modules/aws-sdk-client-mock": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aws-sdk-client-mock/-/aws-sdk-client-mock-3.0.0.tgz", - "integrity": "sha512-4mBiWhuLYLZe1+K/iB8eYy5SAZyW2se+Keyh5u9QouMt6/qJ5SRZhss68xvUX5g3ApzROJ06QPRziYHP6buuvQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/aws-sdk-client-mock/-/aws-sdk-client-mock-3.0.1.tgz", + "integrity": "sha512-9VAzJLl8mz99KP9HjOm/93d8vznRRUTpJooPBOunRdUAnVYopCe9xmMuu7eVemu8fQ+w6rP7o5bBK1kAFkB2KQ==", "dev": true, "dependencies": { "@types/sinon": "^10.0.10", - "sinon": "^14.0.2", + "sinon": "^16.1.3", "tslib": "^2.1.0" } }, "node_modules/aws-sdk-client-mock-jest": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aws-sdk-client-mock-jest/-/aws-sdk-client-mock-jest-3.0.0.tgz", - "integrity": "sha512-oV1rBQZc4UumLbzZAhi8UAehUq+k75hkQYGLrVIP0iJj85Z9xw+EaSsmJke/KQ8Z3vng+Xv1xbounsxpvZpunQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/aws-sdk-client-mock-jest/-/aws-sdk-client-mock-jest-3.0.1.tgz", + "integrity": "sha512-eT0i+XkvitMt7ml2LVUayVd6oiFO7SqLQBEbRId094fs2qlWlL+Png0WuOFVCIcTZgjoK5v81UnKSLwFbbpWqA==", "dev": true, "dependencies": { "@types/jest": "^28.1.3", "tslib": "^2.1.0" }, "peerDependencies": { - "aws-sdk-client-mock": "3.0.0" + "aws-sdk-client-mock": "3.0.1" } }, "node_modules/aws-sdk-client-mock-jest/node_modules/@jest/expect-utils": { @@ -6121,12 +6441,12 @@ } }, "node_modules/axios": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", - "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.7.tgz", + "integrity": "sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==", "dev": true, "dependencies": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.4", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -6279,15 +6599,6 @@ "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", "dev": true }, - "node_modules/big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -6304,26 +6615,13 @@ "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" }, - "node_modules/bplist-parser": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", - "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", - "dev": true, - "dependencies": { - "big-integer": "^1.6.44" - }, - "engines": { - "node": ">= 5.10.0" - } - }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/braces": { @@ -6339,9 +6637,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.0.tgz", - "integrity": "sha512-v+Jcv64L2LbfTC6OnRcaxtqJNJuQAVhZKSJfR/6hn7lhnChUXl4amwVviqN1k411BB+3rRoKMitELRn1CojeRA==", + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", "dev": true, "funding": [ { @@ -6358,9 +6656,9 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001539", - "electron-to-chromium": "^1.4.530", - "node-releases": "^2.0.13", + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, "bin": { @@ -6429,21 +6727,6 @@ "semver": "^7.0.0" } }, - "node_modules/bundle-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", - "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", - "dev": true, - "dependencies": { - "run-applescript": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/byte-size": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/byte-size/-/byte-size-8.1.1.tgz", @@ -6454,17 +6737,17 @@ } }, "node_modules/cacache": { - "version": "17.1.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", - "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", + "version": "18.0.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-18.0.2.tgz", + "integrity": "sha512-r3NU8h/P+4lVUHfeRw1dtgQYar3DZMm4/cm2bZgOvrFC/su7budSOeqh52VJIC4U4iG1WWwV6vRW0znqBvxNuw==", "dev": true, "dependencies": { "@npmcli/fs": "^3.1.0", "fs-minipass": "^3.0.0", "glob": "^10.2.2", - "lru-cache": "^7.7.1", + "lru-cache": "^10.0.1", "minipass": "^7.0.3", - "minipass-collect": "^1.0.2", + "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "p-map": "^4.0.0", @@ -6473,16 +6756,19 @@ "unique-filename": "^3.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/cacache/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/cacache/node_modules/fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0" + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/cacache/node_modules/glob": { @@ -6508,34 +6794,31 @@ } }, "node_modules/cacache/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", "dev": true, "engines": { - "node": ">=12" + "node": "14 || >=16.14" } }, - "node_modules/cacache/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "node_modules/cacache/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, "engines": { "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/cacache/node_modules/minipass": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", - "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", + "node_modules/cacache/node_modules/minipass-collect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-2.0.1.tgz", + "integrity": "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==", "dev": true, + "dependencies": { + "minipass": "^7.0.3" + }, "engines": { "node": ">=16 || 14 >=14.17" } @@ -6553,13 +6836,14 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6601,9 +6885,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001540", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001540.tgz", - "integrity": "sha512-9JL38jscuTJBTcuETxm8QLsFr/F6v0CYYTEU6r5+qSM98P2Q0Hmu0eG1dTG5GBUmywU3UlcVOUSIJYY47rdFSw==", + "version": "1.0.30001577", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001577.tgz", + "integrity": "sha512-rs2ZygrG1PNXMfmncM0B5H1hndY5ZCC9b5TkFaVNfZ+AUlyqcMyVIQtc3fsezi0NUCk5XZfDf9WS6WxMxnfdrg==", "dev": true, "funding": [ { @@ -6670,9 +6954,9 @@ } }, "node_modules/ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, "funding": [ { @@ -6724,16 +7008,16 @@ } }, "node_modules/cli-truncate": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", - "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", "dev": true, "dependencies": { "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" + "string-width": "^7.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -6752,23 +7036,23 @@ } }, "node_modules/cli-truncate/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", "dev": true }, "node_modules/cli-truncate/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", "dev": true, "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -6799,14 +7083,17 @@ } }, "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, "node_modules/cliui/node_modules/wrap-ansi": { @@ -6966,9 +7253,9 @@ } }, "node_modules/commander": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.0.0.tgz", - "integrity": "sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", "dev": true, "engines": { "node": ">=16" @@ -7011,24 +7298,32 @@ "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", "dev": true }, + "node_modules/construct": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/construct/-/construct-1.0.0.tgz", + "integrity": "sha512-AGU/GtcAyDLIToOmzth6/dfynQq7EJuhY4t3nK6Z8aYU+k3/SHOouD1S40q2rALxZN8glMN07jdFsMdVUpomjQ==", + "engines": { + "node": "*" + } + }, "node_modules/constructs": { - "version": "10.2.70", - "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.2.70.tgz", - "integrity": "sha512-z6zr1E8K/9tzJbCQzY0UGX0/oVKPFKu9C/mzEnghCG6TAJINnvlq0CMKm63XqqeMleadZYm5T3sZGJKcxJS/Pg==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.3.0.tgz", + "integrity": "sha512-vbK8i3rIb/xwZxSpTjz3SagHn1qq9BChLEfy5Hf6fB3/2eFbrwt2n9kHwQcS0CPTRBesreeAcsJfMq2229FnbQ==", "engines": { "node": ">= 16.14.0" } }, "node_modules/conventional-changelog-angular": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-6.0.0.tgz", - "integrity": "sha512-6qLgrBF4gueoC7AFVHu51nHL9pF9FRjXrH+ceVf7WmAfH3gs+gEYOkvxhjMPjZu57I4AGUGoNTY8V7Hrgf1uqg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", + "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==", "dev": true, "dependencies": { "compare-func": "^2.0.0" }, "engines": { - "node": ">=14" + "node": ">=16" } }, "node_modules/conventional-changelog-core": { @@ -7312,150 +7607,6 @@ "node": ">=0.10.0" } }, - "node_modules/default-browser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", - "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", - "dev": true, - "dependencies": { - "bundle-name": "^3.0.0", - "default-browser-id": "^3.0.0", - "execa": "^7.1.1", - "titleize": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser-id": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", - "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", - "dev": true, - "dependencies": { - "bplist-parser": "^0.2.0", - "untildify": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser/node_modules/execa": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", - "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/default-browser/node_modules/human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "dev": true, - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/default-browser/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser/node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser/node_modules/npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", - "dev": true, - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser/node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser/node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/defaults": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", @@ -7469,9 +7620,9 @@ } }, "node_modules/define-data-property": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.0.tgz", - "integrity": "sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", "dev": true, "dependencies": { "get-intrinsic": "^1.2.1", @@ -7606,9 +7757,9 @@ } }, "node_modules/dotenv": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", - "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.2.tgz", + "integrity": "sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ==", "dev": true, "engines": { "node": ">=12" @@ -7663,9 +7814,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.532", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.532.tgz", - "integrity": "sha512-piIR0QFdIGKmOJTSNg5AwxZRNWQSXlRYycqDB9Srstx4lip8KpcmRxVP6zuFWExWziHYZpJ0acX7TxqX95KBpg==", + "version": "1.4.632", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.632.tgz", + "integrity": "sha512-JGmudTwg7yxMYvR/gWbalqqQiyu7WTFv2Xu3vw4cJHXPFxNgAk0oy8UHaer8nLF4lZJa+rNoj6GsrKIVJTV6Tw==", "dev": true }, "node_modules/emitter-listener": { @@ -7788,26 +7939,26 @@ } }, "node_modules/es-abstract": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.2.tgz", - "integrity": "sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==", + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", + "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.0", "arraybuffer.prototype.slice": "^1.0.2", "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "call-bind": "^1.0.5", "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.1", + "get-intrinsic": "^1.2.2", "get-symbol-description": "^1.0.0", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has": "^1.0.3", "has-property-descriptors": "^1.0.0", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", + "hasown": "^2.0.0", "internal-slot": "^1.0.5", "is-array-buffer": "^3.0.2", "is-callable": "^1.2.7", @@ -7817,7 +7968,7 @@ "is-string": "^1.0.7", "is-typed-array": "^1.1.12", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", "object.assign": "^4.1.4", "regexp.prototype.flags": "^1.5.1", @@ -7831,7 +7982,7 @@ "typed-array-byte-offset": "^1.0.0", "typed-array-length": "^1.0.4", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.11" + "which-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -7841,26 +7992,26 @@ } }, "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", + "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "get-intrinsic": "^1.2.2", + "has-tostringtag": "^1.0.0", + "hasown": "^2.0.0" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" } }, "node_modules/es-to-primitive": { @@ -7881,9 +8032,9 @@ } }, "node_modules/esbuild": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.3.tgz", - "integrity": "sha512-UlJ1qUUA2jL2nNib1JTSkifQTcYTroFqRjwCFW4QYEKEsixXD5Tik9xML7zh2gTxkYTBKGHNH9y7txMwVyPbjw==", + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.1.tgz", + "integrity": "sha512-OJwEgrpWm/PCMsLVWXKqvcjme3bHNpOgN7Tb6cQnR5n0TPbQx1/Xrn7rqM+wn17bYeT6MGB5sn1Bh5YiGi70nA==", "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" @@ -7892,28 +8043,29 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.19.3", - "@esbuild/android-arm64": "0.19.3", - "@esbuild/android-x64": "0.19.3", - "@esbuild/darwin-arm64": "0.19.3", - "@esbuild/darwin-x64": "0.19.3", - "@esbuild/freebsd-arm64": "0.19.3", - "@esbuild/freebsd-x64": "0.19.3", - "@esbuild/linux-arm": "0.19.3", - "@esbuild/linux-arm64": "0.19.3", - "@esbuild/linux-ia32": "0.19.3", - "@esbuild/linux-loong64": "0.19.3", - "@esbuild/linux-mips64el": "0.19.3", - "@esbuild/linux-ppc64": "0.19.3", - "@esbuild/linux-riscv64": "0.19.3", - "@esbuild/linux-s390x": "0.19.3", - "@esbuild/linux-x64": "0.19.3", - "@esbuild/netbsd-x64": "0.19.3", - "@esbuild/openbsd-x64": "0.19.3", - "@esbuild/sunos-x64": "0.19.3", - "@esbuild/win32-arm64": "0.19.3", - "@esbuild/win32-ia32": "0.19.3", - "@esbuild/win32-x64": "0.19.3" + "@esbuild/aix-ppc64": "0.20.1", + "@esbuild/android-arm": "0.20.1", + "@esbuild/android-arm64": "0.20.1", + "@esbuild/android-x64": "0.20.1", + "@esbuild/darwin-arm64": "0.20.1", + "@esbuild/darwin-x64": "0.20.1", + "@esbuild/freebsd-arm64": "0.20.1", + "@esbuild/freebsd-x64": "0.20.1", + "@esbuild/linux-arm": "0.20.1", + "@esbuild/linux-arm64": "0.20.1", + "@esbuild/linux-ia32": "0.20.1", + "@esbuild/linux-loong64": "0.20.1", + "@esbuild/linux-mips64el": "0.20.1", + "@esbuild/linux-ppc64": "0.20.1", + "@esbuild/linux-riscv64": "0.20.1", + "@esbuild/linux-s390x": "0.20.1", + "@esbuild/linux-x64": "0.20.1", + "@esbuild/netbsd-x64": "0.20.1", + "@esbuild/openbsd-x64": "0.20.1", + "@esbuild/sunos-x64": "0.20.1", + "@esbuild/win32-arm64": "0.20.1", + "@esbuild/win32-ia32": "0.20.1", + "@esbuild/win32-x64": "0.20.1" } }, "node_modules/escalade": { @@ -7938,18 +8090,19 @@ } }, "node_modules/eslint": { - "version": "8.50.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.50.0.tgz", - "integrity": "sha512-FOnOGSuFuFLv/Sa+FDVRZl4GGVAAFFi8LecRsI5a1tMO5HIE8nCm4ivAlzt4dT3ol/PaaGC0rJEEXQmHJBGoOg==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.50.0", - "@humanwhocodes/config-array": "^0.11.11", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -7992,9 +8145,9 @@ } }, "node_modules/eslint-config-prettier": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz", - "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" @@ -8075,28 +8228,28 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.28.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz", - "integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==", + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", "dev": true, "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.findlastindex": "^1.2.2", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", + "eslint-import-resolver-node": "^0.3.9", "eslint-module-utils": "^2.8.0", - "has": "^1.0.3", - "is-core-module": "^2.13.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.fromentries": "^2.0.6", - "object.groupby": "^1.0.0", - "object.values": "^1.1.6", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", "semver": "^6.3.1", - "tsconfig-paths": "^3.14.2" + "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" @@ -8105,6 +8258,16 @@ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" } }, + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/eslint-plugin-import/node_modules/debug": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", @@ -8126,6 +8289,18 @@ "node": ">=0.10.0" } }, + "node_modules/eslint-plugin-import/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, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/eslint-plugin-import/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -8136,23 +8311,24 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.0.tgz", - "integrity": "sha512-AgaZCVuYDXHUGxj/ZGu1u8H8CYgDY3iG6w5kUFw4AzMVXzB7VvbKgYR4nATIN+OvUrghMbiDLeimVjVY5ilq3w==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", + "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", "dev": true, "dependencies": { "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.5" + "synckit": "^0.8.6" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/prettier" + "url": "https://opencollective.com/eslint-plugin-prettier" }, "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", + "eslint-config-prettier": "*", "prettier": ">=3.0.0" }, "peerDependenciesMeta": { @@ -8192,6 +8368,28 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/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, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", @@ -8372,9 +8570,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -8433,9 +8631,9 @@ } }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", + "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -8450,6 +8648,12 @@ "bser": "2.1.1" } }, + "node_modules/fflate": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.1.tgz", + "integrity": "sha512-/exOvEuc+/iaUm105QIiOt4LpBdMTWsXxqR0HDF35vx3fmaKzw7354gTilCh5rkzEt8WYyG//ku3h3nRmd7CHQ==", + "dev": true + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -8495,15 +8699,6 @@ "minimatch": "^5.0.1" } }, - "node_modules/filelist/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/filelist/node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", @@ -8554,17 +8749,17 @@ } }, "node_modules/flat-cache": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz", - "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "dependencies": { - "flatted": "^3.2.7", + "flatted": "^3.2.9", "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { - "node": ">=12.0.0" + "node": "^10.12.0 || >=12.0.0" } }, "node_modules/flat-cache/node_modules/rimraf": { @@ -8589,9 +8784,9 @@ "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", "dev": true, "funding": [ { @@ -8666,9 +8861,9 @@ "dev": true }, "node_modules/fs-extra": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", - "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "dev": true, "dependencies": { "graceful-fs": "^4.2.0", @@ -8680,24 +8875,15 @@ } }, "node_modules/fs-minipass": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "dev": true, "dependencies": { - "minipass": "^7.0.3" + "minipass": "^3.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", - "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">= 8" } }, "node_modules/fs.realpath": { @@ -8720,10 +8906,13 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { "version": "1.1.6", @@ -8789,16 +8978,28 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8831,6 +9032,34 @@ "node": ">=6.9.0" } }, + "node_modules/get-pkg-repo/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/get-pkg-repo/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/get-pkg-repo/node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", @@ -8849,6 +9078,15 @@ "node": ">=10" } }, + "node_modules/get-pkg-repo/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/get-port": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", @@ -9016,10 +9254,32 @@ "node": ">=10.13.0" } }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/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, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/globals": { - "version": "13.22.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.22.0.tgz", - "integrity": "sha512-H1Ddc/PbZHTDVJSnj8kWptIRSD6AM3pK+mKytuIVF4uoBV7rshFlhhvA58ceJ5wp3Er58w6zj7bykMpYXt3ETw==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -9120,18 +9380,6 @@ "node": ">=6" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", @@ -9151,12 +9399,12 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.1" + "get-intrinsic": "^1.2.2" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9219,6 +9467,18 @@ "node": ">=16" } }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/hosted-git-info": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", @@ -9307,15 +9567,15 @@ } }, "node_modules/husky": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", - "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "version": "9.0.11", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", + "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", "dev": true, "bin": { - "husky": "lib/bin.js" + "husky": "bin.mjs" }, "engines": { - "node": ">=14" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/typicode" @@ -9354,9 +9614,9 @@ ] }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", "dev": true, "engines": { "node": ">= 4" @@ -9374,15 +9634,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/ignore-walk/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/ignore-walk/node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", @@ -9551,23 +9802,36 @@ } }, "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", + "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", + "get-intrinsic": "^1.2.2", + "hasown": "^2.0.0", "side-channel": "^1.0.4" }, "engines": { "node": ">= 0.4" } }, - "node_modules/ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dev": true, + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ip-address/node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", "dev": true }, "node_modules/is-arguments": { @@ -9659,12 +9923,12 @@ } }, "node_modules/is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9757,39 +10021,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, - "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-inside-container/node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-interactive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", @@ -10041,18 +10272,18 @@ } }, "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-instrument": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.0.tgz", - "integrity": "sha512-x58orMzEVfzPUKqlbLd1hXCnySCxKdDKa6Rjg97CwuLLRI4g3FHTdnExu1OqffVFay6zeMW+T6/DowFLndWnIw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", + "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", "dev": true, "dependencies": { "@babel/core": "^7.12.3", @@ -10142,6 +10373,28 @@ "node": ">=10" } }, + "node_modules/jake/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/jake/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, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -10746,6 +10999,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "dev": true + }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -10850,15 +11109,15 @@ } }, "node_modules/just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", + "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", "dev": true }, "node_modules/keyv": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", - "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "dependencies": { "json-buffer": "3.0.1" @@ -10887,15 +11146,14 @@ "link": true }, "node_modules/lerna": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/lerna/-/lerna-7.3.0.tgz", - "integrity": "sha512-Dt8TH+J+c9+3MhTYcm5OxnNzXb87WG7GPNj3kidjYJjJY7KxIMDNU37qBTYRWA1h3wAeNKBplXVQYUPkGcYgkQ==", + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/lerna/-/lerna-8.1.2.tgz", + "integrity": "sha512-RCyBAn3XsqqvHbz3TxLfD7ylqzCi1A2UJnFEZmhURgx589vM3qYWQa/uOMeEEf565q6cAdtmulITciX1wgkAtw==", "dev": true, "dependencies": { - "@lerna/child-process": "7.3.0", - "@lerna/create": "7.3.0", - "@npmcli/run-script": "6.0.2", - "@nx/devkit": ">=16.5.1 < 17", + "@lerna/create": "8.1.2", + "@npmcli/run-script": "7.0.2", + "@nx/devkit": ">=17.1.2 < 19", "@octokit/plugin-enterprise-rest": "6.0.1", "@octokit/rest": "19.0.11", "byte-size": "8.1.1", @@ -10903,7 +11161,7 @@ "clone-deep": "4.0.1", "cmd-shim": "6.0.1", "columnify": "1.6.0", - "conventional-changelog-angular": "6.0.0", + "conventional-changelog-angular": "7.0.0", "conventional-changelog-core": "5.0.1", "conventional-recommended-bump": "7.0.1", "cosmiconfig": "^8.2.0", @@ -10938,14 +11196,14 @@ "npm-packlist": "5.1.1", "npm-registry-fetch": "^14.0.5", "npmlog": "^6.0.2", - "nx": ">=16.5.1 < 17", + "nx": ">=17.1.2 < 19", "p-map": "4.0.0", "p-map-series": "2.1.0", "p-pipe": "3.1.0", "p-queue": "6.6.2", "p-reduce": "2.1.0", "p-waterfall": "2.1.1", - "pacote": "^15.2.0", + "pacote": "^17.0.5", "pify": "5.0.0", "read-cmd-shim": "4.0.0", "read-package-json": "6.0.4", @@ -10965,20 +11223,30 @@ "validate-npm-package-name": "5.0.0", "write-file-atomic": "5.0.1", "write-pkg": "4.0.0", - "yargs": "16.2.0", - "yargs-parser": "20.2.4" + "yargs": "17.7.2", + "yargs-parser": "21.1.1" }, "bin": { "lerna": "dist/cli.js" }, "engines": { - "node": "^14.17.0 || >=16.0.0" + "node": ">=18.0.0" } }, - "node_modules/lerna/node_modules/chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "node_modules/lerna/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/lerna/node_modules/chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", "dev": true, "dependencies": { "ansi-styles": "^4.1.0", @@ -11181,24 +11449,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/lerna/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -11311,9 +11561,9 @@ } }, "node_modules/libnpmpublish/node_modules/minipass": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", - "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", "dev": true, "engines": { "node": ">=16 || 14 >=14.17" @@ -11362,45 +11612,45 @@ } }, "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", + "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", "dev": true, "engines": { - "node": ">=10" + "node": ">=14" } }, "node_modules/lines-and-columns": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz", - "integrity": "sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", + "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", "dev": true, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, "node_modules/lint-staged": { - "version": "14.0.1", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-14.0.1.tgz", - "integrity": "sha512-Mw0cL6HXnHN1ag0mN/Dg4g6sr8uf8sn98w2Oc1ECtFto9tvRF7nkXGJRbx8gPlHyoR0pLyBr2lQHbWwmUHe1Sw==", + "version": "15.2.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.2.tgz", + "integrity": "sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==", "dev": true, "dependencies": { "chalk": "5.3.0", - "commander": "11.0.0", + "commander": "11.1.0", "debug": "4.3.4", - "execa": "7.2.0", - "lilconfig": "2.1.0", - "listr2": "6.6.1", + "execa": "8.0.1", + "lilconfig": "3.0.0", + "listr2": "8.0.1", "micromatch": "4.0.5", "pidtree": "0.6.0", "string-argv": "0.3.2", - "yaml": "2.3.1" + "yaml": "2.3.4" }, "bin": { "lint-staged": "bin/lint-staged.js" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": ">=18.12.0" }, "funding": { "url": "https://opencollective.com/lint-staged" @@ -11419,35 +11669,47 @@ } }, "node_modules/lint-staged/node_modules/execa": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", - "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", "dev": true, "dependencies": { "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", - "signal-exit": "^3.0.7", + "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" }, "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + "node": ">=16.17" }, "funding": { "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/lint-staged/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/lint-staged/node_modules/human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "dev": true, "engines": { - "node": ">=14.18.0" + "node": ">=16.17.0" } }, "node_modules/lint-staged/node_modules/is-stream": { @@ -11475,9 +11737,9 @@ } }, "node_modules/lint-staged/node_modules/npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.2.0.tgz", + "integrity": "sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==", "dev": true, "dependencies": { "path-key": "^4.0.0" @@ -11516,6 +11778,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lint-staged/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/lint-staged/node_modules/strip-final-newline": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", @@ -11529,28 +11803,20 @@ } }, "node_modules/listr2": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-6.6.1.tgz", - "integrity": "sha512-+rAXGHh0fkEWdXBmX+L6mmfmXmXvDGEKzkjxO+8mP3+nI/r/CWznVBvsibXdxda9Zz0OW2e2ikphN3OwCT/jSg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.0.1.tgz", + "integrity": "sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==", "dev": true, "dependencies": { - "cli-truncate": "^3.1.0", + "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", - "log-update": "^5.0.1", + "log-update": "^6.0.0", "rfdc": "^1.3.0", - "wrap-ansi": "^8.1.0" + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" - }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } + "node": ">=18.0.0" } }, "node_modules/listr2/node_modules/ansi-regex": { @@ -11578,23 +11844,23 @@ } }, "node_modules/listr2/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", "dev": true }, "node_modules/listr2/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", "dev": true, "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -11616,17 +11882,17 @@ } }, "node_modules/listr2/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" @@ -11717,34 +11983,34 @@ } }, "node_modules/log-update": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-5.0.1.tgz", - "integrity": "sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", + "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", "dev": true, "dependencies": { - "ansi-escapes": "^5.0.0", + "ansi-escapes": "^6.2.0", "cli-cursor": "^4.0.0", - "slice-ansi": "^5.0.0", - "strip-ansi": "^7.0.1", - "wrap-ansi": "^8.0.1" + "slice-ansi": "^7.0.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/log-update/node_modules/ansi-escapes": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-5.0.0.tgz", - "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", + "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", "dev": true, "dependencies": { - "type-fest": "^1.0.2" + "type-fest": "^3.0.0" }, "engines": { - "node": ">=12" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -11790,11 +12056,26 @@ } }, "node_modules/log-update/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", "dev": true }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", + "dev": true, + "dependencies": { + "get-east-asian-width": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/log-update/node_modules/restore-cursor": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", @@ -11811,18 +12092,34 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, "node_modules/log-update/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", "dev": true, "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -11844,29 +12141,29 @@ } }, "node_modules/log-update/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", "dev": true, "engines": { - "node": ">=10" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/log-update/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" @@ -11909,38 +12206,34 @@ "dev": true }, "node_modules/make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz", + "integrity": "sha512-7ThobcL8brtGo9CavByQrQi+23aIfgYU++wg4B87AIS8Rb2ZBt/MEaDqzA00Xwv/jUjAjYkLHjVolYuTLKda2A==", "dev": true, "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", + "@npmcli/agent": "^2.0.0", + "cacache": "^18.0.0", "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", + "minipass": "^7.0.2", "minipass-fetch": "^3.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^0.6.3", "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", "ssri": "^10.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "node_modules/make-fetch-happen/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", "dev": true, "engines": { - "node": ">=12" + "node": ">=16 || 14 >=14.17" } }, "node_modules/make-fetch-happen/node_modules/ssri": { @@ -11955,15 +12248,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/make-fetch-happen/node_modules/ssri/node_modules/minipass": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", - "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", - "dev": true, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", @@ -12163,6 +12447,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/meow/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -12231,15 +12524,18 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { @@ -12266,10 +12562,13 @@ } }, "node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, "engines": { "node": ">=8" } @@ -12286,24 +12585,6 @@ "node": ">= 8" } }, - "node_modules/minipass-collect/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-collect/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/minipass-fetch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", @@ -12322,9 +12603,9 @@ } }, "node_modules/minipass-fetch/node_modules/minipass": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", - "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", "dev": true, "engines": { "node": ">=16 || 14 >=14.17" @@ -12342,24 +12623,6 @@ "node": ">= 8" } }, - "node_modules/minipass-flush/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-flush/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/minipass-json-stream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", @@ -12370,24 +12633,6 @@ "minipass": "^3.0.0" } }, - "node_modules/minipass-json-stream/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-json-stream/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/minipass-pipeline": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", @@ -12400,49 +12645,19 @@ "node": ">=8" } }, - "node_modules/minipass-pipeline/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", "dev": true, "dependencies": { - "yallist": "^4.0.0" + "minipass": "^3.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/minipass-pipeline/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized/node_modules/yallist": { + "node_modules/minipass/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", @@ -12461,18 +12676,6 @@ "node": ">= 8" } }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/minizlib/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -12495,6 +12698,7 @@ "version": "0.38.3", "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.3.tgz", "integrity": "sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==", + "dev": true, "dependencies": { "obliterator": "^1.6.1" } @@ -12542,6 +12746,28 @@ "node": ">=8" } }, + "node_modules/multimatch/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/multimatch/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, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", @@ -12570,33 +12796,27 @@ "dev": true }, "node_modules/nise": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", - "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.7.tgz", + "integrity": "sha512-wWtNUhkT7k58uvWTB/Gy26eA/EJKtPZFVAhEilN5UYVmmGRYOURbejRUyKm0Uu9XVEW7K5nBOZfR8VMB4QR2RQ==", "dev": true, "dependencies": { - "@sinonjs/commons": "^2.0.0", - "@sinonjs/fake-timers": "^10.0.2", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" + "@sinonjs/commons": "^3.0.0", + "@sinonjs/fake-timers": "^11.2.2", + "@sinonjs/text-encoding": "^0.7.2", + "just-extend": "^6.2.0", + "path-to-regexp": "^6.2.1" } }, - "node_modules/nise/node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "node_modules/nise/node_modules/@sinonjs/fake-timers": { + "version": "11.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz", + "integrity": "sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw==", "dev": true, "dependencies": { - "type-detect": "4.0.8" + "@sinonjs/commons": "^3.0.0" } }, - "node_modules/node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true - }, "node_modules/node-fetch": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", @@ -12618,54 +12838,82 @@ } }, "node_modules/node-gyp": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.0.tgz", - "integrity": "sha512-dMXsYP6gc9rRbejLXmTbVRYjAHw7ppswsKyMxuxJxxOHzluIO1rGp9TOQgjFJ+2MCqcOcQTOPB/8Xwhr+7s4Eg==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.0.1.tgz", + "integrity": "sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg==", "dev": true, "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", - "glob": "^7.1.4", + "glob": "^10.3.10", "graceful-fs": "^4.2.6", - "make-fetch-happen": "^11.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", + "make-fetch-happen": "^13.0.0", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", "semver": "^7.3.5", "tar": "^6.1.2", - "which": "^2.0.2" + "which": "^4.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" }, "engines": { - "node": "^12.13 || ^14.13 || >=16" + "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/node-gyp-build": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.1.tgz", - "integrity": "sha512-24vnklJmyRS8ViBNI8KbtK/r/DmXQMRiOMXTNz2nrTnAYUwjmEEbnnpB/+kt+yWRv73bPsSPRFddrcIbAxSiMQ==", + "node_modules/node-gyp/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/node-gyp/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/node-gyp/node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/node-gyp/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/node-gyp/node_modules/which": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", + "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", "dev": true, "dependencies": { - "glob": "^7.1.3" + "isexe": "^3.1.1" }, "bin": { - "rimraf": "bin.js" + "node-which": "bin/which.js" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": "^16.13.0 || >=18.0.0" } }, "node_modules/node-int64": { @@ -12681,24 +12929,24 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, "node_modules/nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", + "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", "dev": true, "dependencies": { - "abbrev": "^1.0.0" + "abbrev": "^2.0.0" }, "bin": { "nopt": "bin/nopt.js" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/normalize-package-data": { @@ -12735,9 +12983,9 @@ } }, "node_modules/npm-install-checks": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.2.0.tgz", - "integrity": "sha512-744wat5wAAHsxa4590mWO0tJ8PKxR8ORZsH9wGpQc3nWTzozMAgBN/XyqYw7mg3yqLM8dLwEnwSfKMmXAjF69g==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz", + "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==", "dev": true, "dependencies": { "semver": "^7.1.1" @@ -12829,15 +13077,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/npm-packlist/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/npm-packlist/node_modules/glob": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", @@ -12870,39 +13109,39 @@ } }, "node_modules/npm-pick-manifest": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-8.0.2.tgz", - "integrity": "sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-9.0.0.tgz", + "integrity": "sha512-VfvRSs/b6n9ol4Qb+bDwNGUXutpy76x6MARw/XssevE0TnctIKcmklJZM5Z7nqs5z5aW+0S63pgCNbpkUNNXBg==", "dev": true, "dependencies": { "npm-install-checks": "^6.0.0", "npm-normalize-package-bin": "^3.0.0", - "npm-package-arg": "^10.0.0", + "npm-package-arg": "^11.0.0", "semver": "^7.3.5" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^16.14.0 || >=18.0.0" } }, "node_modules/npm-pick-manifest/node_modules/hosted-git-info": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", - "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.1.tgz", + "integrity": "sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==", "dev": true, "dependencies": { - "lru-cache": "^7.5.1" + "lru-cache": "^10.0.1" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^16.14.0 || >=18.0.0" } }, "node_modules/npm-pick-manifest/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", "dev": true, "engines": { - "node": ">=12" + "node": "14 || >=16.14" } }, "node_modules/npm-pick-manifest/node_modules/npm-normalize-package-bin": { @@ -12915,18 +13154,18 @@ } }, "node_modules/npm-pick-manifest/node_modules/npm-package-arg": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", - "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz", + "integrity": "sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==", "dev": true, "dependencies": { - "hosted-git-info": "^6.0.0", + "hosted-git-info": "^7.0.0", "proc-log": "^3.0.0", "semver": "^7.3.5", "validate-npm-package-name": "^5.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^16.14.0 || >=18.0.0" } }, "node_modules/npm-registry-fetch": { @@ -12947,6 +13186,81 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/npm-registry-fetch/node_modules/cacache": { + "version": "17.1.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", + "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", + "dev": true, + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^7.7.1", + "minipass": "^7.0.3", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-registry-fetch/node_modules/cacache/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/npm-registry-fetch/node_modules/fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-registry-fetch/node_modules/fs-minipass/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/npm-registry-fetch/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/npm-registry-fetch/node_modules/hosted-git-info": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", @@ -12968,6 +13282,41 @@ "node": ">=12" } }, + "node_modules/npm-registry-fetch/node_modules/make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-registry-fetch/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/npm-registry-fetch/node_modules/npm-package-arg": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", @@ -12983,6 +13332,27 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/npm-registry-fetch/node_modules/ssri": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", + "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-registry-fetch/node_modules/ssri/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -13011,131 +13381,96 @@ } }, "node_modules/nx": { - "version": "16.9.1", - "resolved": "https://registry.npmjs.org/nx/-/nx-16.9.1.tgz", - "integrity": "sha512-h6jp0fXzEsBO3pwCNS2JbfzJZRgE2DnIo7Sj1/1oBo82o44jNqsPo3nMTj95qhcveJ0qBiKIh+Xw/fghXiRiSQ==", + "version": "18.0.3", + "resolved": "https://registry.npmjs.org/nx/-/nx-18.0.3.tgz", + "integrity": "sha512-Lvkd+er641xrBqA7kdEnzf7zvLIEmqLouzONByVZtRrk1BbgEjapUj9r+QLBxXTvmhS7tHFLNiMh1KgpDOWsLQ==", "dev": true, "hasInstallScript": true, "dependencies": { - "@nrwl/tao": "16.9.1", - "@parcel/watcher": "2.0.4", + "@nrwl/tao": "18.0.3", "@yarnpkg/lockfile": "^1.1.0", "@yarnpkg/parsers": "3.0.0-rc.46", "@zkochan/js-yaml": "0.0.6", - "axios": "^1.0.0", + "axios": "^1.6.0", "chalk": "^4.1.0", "cli-cursor": "3.1.0", "cli-spinners": "2.6.1", - "cliui": "^7.0.2", + "cliui": "^8.0.1", "dotenv": "~16.3.1", "dotenv-expand": "~10.0.0", "enquirer": "~2.3.6", "figures": "3.2.0", "flat": "^5.0.2", "fs-extra": "^11.1.0", - "glob": "7.1.4", "ignore": "^5.0.4", "jest-diff": "^29.4.1", "js-yaml": "4.1.0", "jsonc-parser": "3.2.0", "lines-and-columns": "~2.0.3", - "minimatch": "3.0.5", + "minimatch": "9.0.3", "node-machine-id": "1.1.12", "npm-run-path": "^4.0.1", "open": "^8.4.0", - "semver": "7.5.3", + "ora": "5.3.0", + "semver": "^7.5.3", "string-width": "^4.2.3", "strong-log-transformer": "^2.1.0", "tar-stream": "~2.2.0", "tmp": "~0.2.1", "tsconfig-paths": "^4.1.2", "tslib": "^2.3.0", - "v8-compile-cache": "2.3.0", "yargs": "^17.6.2", "yargs-parser": "21.1.1" }, "bin": { - "nx": "bin/nx.js" - }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "16.9.1", - "@nx/nx-darwin-x64": "16.9.1", - "@nx/nx-freebsd-x64": "16.9.1", - "@nx/nx-linux-arm-gnueabihf": "16.9.1", - "@nx/nx-linux-arm64-gnu": "16.9.1", - "@nx/nx-linux-arm64-musl": "16.9.1", - "@nx/nx-linux-x64-gnu": "16.9.1", - "@nx/nx-linux-x64-musl": "16.9.1", - "@nx/nx-win32-arm64-msvc": "16.9.1", - "@nx/nx-win32-x64-msvc": "16.9.1" - }, - "peerDependencies": { - "@swc-node/register": "^1.6.7", - "@swc/core": "^1.3.85" - }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } - } - }, - "node_modules/nx/node_modules/glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/nx/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" }, - "engines": { - "node": ">=10" - } - }, - "node_modules/nx/node_modules/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" + "optionalDependencies": { + "@nx/nx-darwin-arm64": "18.0.3", + "@nx/nx-darwin-x64": "18.0.3", + "@nx/nx-freebsd-x64": "18.0.3", + "@nx/nx-linux-arm-gnueabihf": "18.0.3", + "@nx/nx-linux-arm64-gnu": "18.0.3", + "@nx/nx-linux-arm64-musl": "18.0.3", + "@nx/nx-linux-x64-gnu": "18.0.3", + "@nx/nx-linux-x64-musl": "18.0.3", + "@nx/nx-win32-arm64-msvc": "18.0.3", + "@nx/nx-win32-x64-msvc": "18.0.3" }, - "engines": { - "node": "*" + "peerDependencies": { + "@swc-node/register": "^1.6.7", + "@swc/core": "^1.3.85" + }, + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } } }, - "node_modules/nx/node_modules/semver": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "node_modules/nx/node_modules/ora": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.3.0.tgz", + "integrity": "sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==", "dev": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "bl": "^4.0.3", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "log-symbols": "^4.0.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/nx/node_modules/strip-bom": { @@ -13161,25 +13496,10 @@ "node": ">=6" } }, - "node_modules/nx/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/nx/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -13195,13 +13515,13 @@ } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, @@ -13261,7 +13581,8 @@ "node_modules/obliterator": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-1.6.1.tgz", - "integrity": "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==" + "integrity": "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig==", + "dev": true }, "node_modules/once": { "version": "1.4.0", @@ -13496,62 +13817,149 @@ } }, "node_modules/pacote": { - "version": "15.2.0", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-15.2.0.tgz", - "integrity": "sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA==", + "version": "17.0.6", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-17.0.6.tgz", + "integrity": "sha512-cJKrW21VRE8vVTRskJo78c/RCvwJCn1f4qgfxL4w77SOWrTCRcmfkYHlHtS0gqpgjv3zhXflRtgsrUCX5xwNnQ==", "dev": true, "dependencies": { - "@npmcli/git": "^4.0.0", + "@npmcli/git": "^5.0.0", "@npmcli/installed-package-contents": "^2.0.1", - "@npmcli/promise-spawn": "^6.0.1", - "@npmcli/run-script": "^6.0.0", - "cacache": "^17.0.0", + "@npmcli/promise-spawn": "^7.0.0", + "@npmcli/run-script": "^7.0.0", + "cacache": "^18.0.0", "fs-minipass": "^3.0.0", - "minipass": "^5.0.0", - "npm-package-arg": "^10.0.0", - "npm-packlist": "^7.0.0", - "npm-pick-manifest": "^8.0.0", - "npm-registry-fetch": "^14.0.0", + "minipass": "^7.0.2", + "npm-package-arg": "^11.0.0", + "npm-packlist": "^8.0.0", + "npm-pick-manifest": "^9.0.0", + "npm-registry-fetch": "^16.0.0", "proc-log": "^3.0.0", "promise-retry": "^2.0.1", - "read-package-json": "^6.0.0", + "read-package-json": "^7.0.0", "read-package-json-fast": "^3.0.0", - "sigstore": "^1.3.0", + "sigstore": "^2.2.0", "ssri": "^10.0.0", "tar": "^6.1.11" }, "bin": { "pacote": "lib/bin.js" }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/pacote/node_modules/@sigstore/bundle": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-2.1.1.tgz", + "integrity": "sha512-v3/iS+1nufZdKQ5iAlQKcCsoh0jffQyABvYIxKsZQFWc4ubuGjwZklFHpDgV6O6T7vvV78SW5NHI91HFKEcxKg==", + "dev": true, + "dependencies": { + "@sigstore/protobuf-specs": "^0.2.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/pacote/node_modules/@sigstore/sign": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-2.2.2.tgz", + "integrity": "sha512-mAifqvvGOCkb5BJ5d/SRrVP5+kKCGxtcHuti6lgqZalIfNxikxlJMMptOqFp9+xV5LAnJMSaMWtzvcgNZ3PlPA==", + "dev": true, + "dependencies": { + "@sigstore/bundle": "^2.1.1", + "@sigstore/core": "^1.0.0", + "@sigstore/protobuf-specs": "^0.2.1", + "make-fetch-happen": "^13.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/pacote/node_modules/@sigstore/tuf": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-2.3.0.tgz", + "integrity": "sha512-S98jo9cpJwO1mtQ+2zY7bOdcYyfVYCUaofCG6wWRzk3pxKHVAkSfshkfecto2+LKsx7Ovtqbgb2LS8zTRhxJ9Q==", + "dev": true, + "dependencies": { + "@sigstore/protobuf-specs": "^0.2.1", + "tuf-js": "^2.2.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/pacote/node_modules/@tufjs/canonical-json": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-2.0.0.tgz", + "integrity": "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA==", + "dev": true, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/pacote/node_modules/@tufjs/models": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-2.0.0.tgz", + "integrity": "sha512-c8nj8BaOExmZKO2DXhDfegyhSGcG9E/mPN3U13L+/PsoWm1uaGiHHjxqSHQiasDBQwDA3aHuw9+9spYAP1qvvg==", + "dev": true, + "dependencies": { + "@tufjs/canonical-json": "2.0.0", + "minimatch": "^9.0.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/pacote/node_modules/fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3" + }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/pacote/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/pacote/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/pacote/node_modules/hosted-git-info": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", - "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.1.tgz", + "integrity": "sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==", "dev": true, "dependencies": { - "lru-cache": "^7.5.1" + "lru-cache": "^10.0.1" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^16.14.0 || >=18.0.0" } }, "node_modules/pacote/node_modules/ignore-walk": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.3.tgz", - "integrity": "sha512-C7FfFoTA+bI10qfeydT8aZbvr91vAEU+2W5BZUlzPec47oNb07SsOfwYrtxuvOYdUApPP/Qlh4DtAO51Ekk2QA==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.4.tgz", + "integrity": "sha512-t7sv42WkwFkyKbivUCglsQW5YWMskWtbEf4MNKX5u/CCWHKSPzN4FtBQGsQZgCLbxOzpVlcbWVK5KB3auIOjSw==", "dev": true, "dependencies": { "minimatch": "^9.0.0" @@ -13560,57 +13968,134 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/pacote/node_modules/json-parse-even-better-errors": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", + "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, "node_modules/pacote/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", "dev": true, "engines": { - "node": ">=12" + "node": "14 || >=16.14" } }, - "node_modules/pacote/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "node_modules/pacote/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, "engines": { "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/pacote/node_modules/normalize-package-data": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.0.tgz", + "integrity": "sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==", + "dev": true, + "dependencies": { + "hosted-git-info": "^7.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/pacote/node_modules/npm-normalize-package-bin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", + "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/pacote/node_modules/npm-package-arg": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", - "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-11.0.1.tgz", + "integrity": "sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==", "dev": true, "dependencies": { - "hosted-git-info": "^6.0.0", + "hosted-git-info": "^7.0.0", "proc-log": "^3.0.0", "semver": "^7.3.5", "validate-npm-package-name": "^5.0.0" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": "^16.14.0 || >=18.0.0" } }, "node_modules/pacote/node_modules/npm-packlist": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-7.0.4.tgz", - "integrity": "sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-8.0.2.tgz", + "integrity": "sha512-shYrPFIS/JLP4oQmAwDyk5HcyysKW8/JLTEA32S0Z5TzvpaeeX2yMFfoK1fjEBnCBvVyIB/Jj/GBFdm0wsgzbA==", "dev": true, "dependencies": { - "ignore-walk": "^6.0.0" + "ignore-walk": "^6.0.4" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/pacote/node_modules/npm-registry-fetch": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-16.1.0.tgz", + "integrity": "sha512-PQCELXKt8Azvxnt5Y85GseQDJJlglTFM9L9U9gkv2y4e9s0k3GVDdOx3YoB6gm2Do0hlkzC39iCGXby+Wve1Bw==", + "dev": true, + "dependencies": { + "make-fetch-happen": "^13.0.0", + "minipass": "^7.0.2", + "minipass-fetch": "^3.0.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^11.0.0", + "proc-log": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/pacote/node_modules/read-package-json": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-7.0.0.tgz", + "integrity": "sha512-uL4Z10OKV4p6vbdvIXB+OzhInYtIozl/VxUBPgNkBuUi2DeRonnuspmaVAMcrkmfjKGNmRndyQAbE7/AmzGwFg==", + "dev": true, + "dependencies": { + "glob": "^10.2.2", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/pacote/node_modules/sigstore": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-2.2.1.tgz", + "integrity": "sha512-OBBSKvmjr4DCyUb+IC2p7wooOCsCNwaqvCilTJVNPo0y8lJl+LsCrfz4LtMwnw3Gn+8frt816wi1+DWZTUCpBQ==", + "dev": true, + "dependencies": { + "@sigstore/bundle": "^2.1.1", + "@sigstore/core": "^1.0.0", + "@sigstore/protobuf-specs": "^0.2.1", + "@sigstore/sign": "^2.2.2", + "@sigstore/tuf": "^2.3.0", + "@sigstore/verify": "^1.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, "node_modules/pacote/node_modules/ssri": { "version": "10.0.5", "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", @@ -13623,13 +14108,18 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/pacote/node_modules/ssri/node_modules/minipass": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", - "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", + "node_modules/pacote/node_modules/tuf-js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-2.2.0.tgz", + "integrity": "sha512-ZSDngmP1z6zw+FIkIBjvOp/II/mIub/O7Pp12j1WNsiCpg5R5wAc//i555bBQsE44O94btLt0xM/Zr2LQjwdCg==", "dev": true, + "dependencies": { + "@tufjs/models": "2.0.0", + "debug": "^4.3.4", + "make-fetch-happen": "^13.0.0" + }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "^16.14.0 || >=18.0.0" } }, "node_modules/parent-module": { @@ -13736,27 +14226,27 @@ } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", - "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", + "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", "dev": true, "engines": { "node": "14 || >=16.14" } }, - "node_modules/path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "node_modules/path-scurry/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", "dev": true, - "dependencies": { - "isarray": "0.0.1" + "engines": { + "node": ">=16 || 14 >=14.17" } }, - "node_modules/path-to-regexp/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "node_modules/path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", "dev": true }, "node_modules/path-type": { @@ -13904,9 +14394,9 @@ } }, "node_modules/prettier": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", - "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -14028,9 +14518,9 @@ "dev": true }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { "node": ">=6" @@ -14160,9 +14650,9 @@ } }, "node_modules/read-package-json-fast/node_modules/json-parse-even-better-errors": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", - "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", + "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==", "dev": true, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" @@ -14177,15 +14667,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/read-package-json/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/read-package-json/node_modules/glob": { "version": "10.3.10", "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", @@ -14221,9 +14702,9 @@ } }, "node_modules/read-package-json/node_modules/json-parse-even-better-errors": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", - "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.1.tgz", + "integrity": "sha512-aatBvbL26wVUCLmbWdCpeu9iF5wOyWpagiKkInA+kfws3sWdBrTnsvN2CKcyCYyUrc7rebNBlK6+kteg7ksecg==", "dev": true, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0" @@ -14238,19 +14719,13 @@ "node": ">=12" } }, - "node_modules/read-package-json/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "node_modules/read-package-json/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, "engines": { "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" } }, "node_modules/read-package-json/node_modules/normalize-package-data": { @@ -14519,9 +14994,9 @@ } }, "node_modules/resolve": { - "version": "1.22.6", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", - "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "dependencies": { "is-core-module": "^2.13.0", @@ -14625,90 +15100,11 @@ } }, "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==", "dev": true }, - "node_modules/rimraf": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", - "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", - "dev": true, - "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-applescript": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", - "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", - "dev": true, - "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", @@ -14751,13 +15147,13 @@ } }, "node_modules/safe-array-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", - "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", + "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -14789,15 +15185,18 @@ ] }, "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.2.tgz", + "integrity": "sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", "is-regex": "^1.1.4" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -14854,6 +15253,22 @@ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, + "node_modules/set-function-length": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz", + "integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.1", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.2", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/set-function-name": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", @@ -14902,9 +15317,9 @@ } }, "node_modules/shiki": { - "version": "0.14.4", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.4.tgz", - "integrity": "sha512-IXCRip2IQzKwxArNNq1S+On4KPML3Yyn8Zzs/xRgcgOWIr8ntIK3IKzjFPfjy/7kt9ZMjc+FItfqHRBg8b6tNQ==", + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.7.tgz", + "integrity": "sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==", "dev": true, "dependencies": { "ansi-sequence-parser": "^1.1.0", @@ -14957,49 +15372,162 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/sinon": { - "version": "14.0.2", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-14.0.2.tgz", - "integrity": "sha512-PDpV0ZI3ZCS3pEqx0vpNp6kzPhHrLx72wA0G+ZLaaJjLIYeE0n8INlgaohKuGy7hP0as5tbUd23QWu5U233t+w==", + "node_modules/sigstore/node_modules/cacache": { + "version": "17.1.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", + "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", "dev": true, "dependencies": { - "@sinonjs/commons": "^2.0.0", - "@sinonjs/fake-timers": "^9.1.2", - "@sinonjs/samsam": "^7.0.1", - "diff": "^5.0.0", - "nise": "^5.1.2", - "supports-color": "^7.2.0" + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^7.7.1", + "minipass": "^7.0.3", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/sigstore/node_modules/cacache/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sigstore/node_modules/fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/sigstore/node_modules/fs-minipass/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sigstore/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/sinon/node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "node_modules/sigstore/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/sigstore/node_modules/make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", "dev": true, "dependencies": { - "type-detect": "4.0.8" + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/sigstore/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/sinon/node_modules/@sinonjs/fake-timers": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz", - "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==", + "node_modules/sigstore/node_modules/ssri": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", + "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", "dev": true, "dependencies": { - "@sinonjs/commons": "^1.7.0" + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/sinon/node_modules/@sinonjs/fake-timers/node_modules/@sinonjs/commons": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", - "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "node_modules/sigstore/node_modules/ssri/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sinon": { + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-16.1.3.tgz", + "integrity": "sha512-mjnWWeyxcAf9nC0bXcPmiDut+oE8HYridTNzBbF98AYVLmWwGRp2ISEpyhYflG1ifILT+eNn3BmKUJPxjXUPlA==", "dev": true, "dependencies": { - "type-detect": "4.0.8" + "@sinonjs/commons": "^3.0.0", + "@sinonjs/fake-timers": "^10.3.0", + "@sinonjs/samsam": "^8.0.0", + "diff": "^5.1.0", + "nise": "^5.1.4", + "supports-color": "^7.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" } }, "node_modules/sinon/node_modules/diff": { @@ -15065,16 +15593,16 @@ } }, "node_modules/socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.3.tgz", + "integrity": "sha512-vfuYK48HXCTFD03G/1/zkIls3Ebr2YNa4qU9gHDZdblHLiqhJrJGkY3+0Nx0JpN9qBhJbVObc1CNciT1bIZJxw==", "dev": true, "dependencies": { - "ip": "^2.0.0", + "ip-address": "^9.0.5", "smart-buffer": "^4.2.0" }, "engines": { - "node": ">= 10.13.0", + "node": ">= 10.0.0", "npm": ">= 3.0.0" } }, @@ -15132,9 +15660,9 @@ } }, "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.4.0.tgz", + "integrity": "sha512-hcjppoJ68fhxA/cjbN4T8N6uCUejN8yFw69ttpqtBeCbF3u13n7mb31NB9jKwGTTWWnt9IbRA/mf1FprYS8wfw==", "dev": true }, "node_modules/spdx-expression-parse": { @@ -15148,9 +15676,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.15.tgz", - "integrity": "sha512-lpT8hSQp9jAKp9mhtBU4Xjon8LPGBvLIuBiSVhMEtmLecTh2mO0tlqrAMp47tBXzMr13NJMQ2lf7RpQGLJ3HsQ==", + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", + "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", "dev": true }, "node_modules/split": { @@ -15192,24 +15720,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/ssri/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ssri/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/stack-chain": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/stack-chain/-/stack-chain-1.3.7.tgz", @@ -15473,13 +15983,13 @@ } }, "node_modules/synckit": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", - "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", "dev": true, "dependencies": { - "@pkgr/utils": "^2.3.1", - "tslib": "^2.5.0" + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -15523,35 +16033,11 @@ "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tar/node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/tar/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" }, "engines": { - "node": ">=8" + "node": ">=6" } }, "node_modules/tar/node_modules/yallist": { @@ -15583,6 +16069,28 @@ "node": ">=8" } }, + "node_modules/test-exclude/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/test-exclude/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, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/text-extensions": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", @@ -15650,18 +16158,6 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/titleize": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", - "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/tmp": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", @@ -15744,9 +16240,9 @@ } }, "node_modules/ts-jest": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", - "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "version": "29.1.2", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.2.tgz", + "integrity": "sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g==", "dev": true, "dependencies": { "bs-logger": "0.x", @@ -15762,7 +16258,7 @@ "ts-jest": "cli.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^16.10.0 || ^18.0.0 || >=20.0.0" }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", @@ -15786,19 +16282,10 @@ } } }, - "node_modules/ts-jest/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", @@ -15839,9 +16326,9 @@ } }, "node_modules/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "dependencies": { "@types/json5": "^0.0.29", @@ -15890,6 +16377,146 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/tuf-js/node_modules/cacache": { + "version": "17.1.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", + "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", + "dev": true, + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^7.7.1", + "minipass": "^7.0.3", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/tuf-js/node_modules/cacache/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/tuf-js/node_modules/fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/tuf-js/node_modules/fs-minipass/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/tuf-js/node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/tuf-js/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/tuf-js/node_modules/make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/tuf-js/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tuf-js/node_modules/ssri": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", + "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/tuf-js/node_modules/ssri/node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -15995,15 +16622,15 @@ "dev": true }, "node_modules/typedoc": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.1.tgz", - "integrity": "sha512-c2ye3YUtGIadxN2O6YwPEXgrZcvhlZ6HlhWZ8jQRNzwLPn2ylhdGqdR8HbyDRyALP8J6lmSANILCkkIdNPFxqA==", + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.11.tgz", + "integrity": "sha512-5MbI1W/FOG6oXsd8bdssQidSTeKh8Kt3xA5uKVzI+K99uzP8EGN45uPnPvQesyaWdD+89s4wCQdtWEd8QUbiRg==", "dev": true, "dependencies": { "lunr": "^2.3.9", "marked": "^4.3.0", "minimatch": "^9.0.3", - "shiki": "^0.14.1" + "shiki": "^0.14.7" }, "bin": { "typedoc": "bin/typedoc" @@ -16012,46 +16639,22 @@ "node": ">= 16" }, "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x" + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x" } }, "node_modules/typedoc-plugin-missing-exports": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/typedoc-plugin-missing-exports/-/typedoc-plugin-missing-exports-2.1.0.tgz", - "integrity": "sha512-+1DhqZCEu7Vu5APnrqpPwl31D+hXpt1fV0Le9ycCRL1eLVdatdl6KVt4SEVwPxnEpKwgOn2dNX6I9+0F1aO2aA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/typedoc-plugin-missing-exports/-/typedoc-plugin-missing-exports-2.2.0.tgz", + "integrity": "sha512-2+XR1IcyQ5UwXZVJe9NE6HrLmNufT9i5OwoIuuj79VxuA3eYq+Y6itS9rnNV1D7UeQnUSH8kISYD73gHE5zw+w==", "dev": true, "peerDependencies": { "typedoc": "0.24.x || 0.25.x" } }, - "node_modules/typedoc/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/typedoc/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -16089,6 +16692,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, "node_modules/unique-filename": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", @@ -16114,29 +16722,20 @@ } }, "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", "dev": true }, "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "engines": { "node": ">= 10.0.0" } }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/upath": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz", @@ -16229,12 +16828,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -16242,25 +16835,19 @@ "dev": true }, "node_modules/v8-to-istanbul": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", - "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" + "convert-source-map": "^2.0.0" }, "engines": { "node": ">=10.12.0" } }, - "node_modules/v8-to-istanbul/node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -16361,13 +16948,13 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", - "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", "dev": true, "dependencies": { "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "call-bind": "^1.0.4", "for-each": "^0.3.3", "gopd": "^1.0.1", "has-tostringtag": "^1.0.0" @@ -16528,9 +17115,9 @@ } }, "node_modules/xml2js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", - "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", "dev": true, "dependencies": { "sax": ">=0.6.0", @@ -16574,9 +17161,9 @@ "dev": true }, "node_modules/yaml": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", - "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", "dev": true, "engines": { "node": ">= 14" @@ -16601,46 +17188,6 @@ } }, "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/yargs/node_modules/yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", @@ -16681,7 +17228,7 @@ }, "packages/batch": { "name": "@aws-lambda-powertools/batch", - "version": "1.14.0", + "version": "2.0.2", "license": "MIT-0", "devDependencies": { "@aws-lambda-powertools/testing-utils": "file:../testing" @@ -16689,7 +17236,7 @@ }, "packages/commons": { "name": "@aws-lambda-powertools/commons", - "version": "1.14.0", + "version": "2.0.2", "license": "MIT-0", "devDependencies": { "@aws-lambda-powertools/testing-utils": "file:../testing" @@ -16697,20 +17244,20 @@ }, "packages/idempotency": { "name": "@aws-lambda-powertools/idempotency", - "version": "1.14.0", + "version": "2.0.2", "license": "MIT-0", "dependencies": { - "@aws-lambda-powertools/commons": "^1.14.0", + "@aws-lambda-powertools/commons": "^2.0.2", "@aws-sdk/util-base64-node": "^3.209.0", "jmespath": "^0.16.0" }, "devDependencies": { "@aws-lambda-powertools/testing-utils": "file:../testing", - "@aws-sdk/client-dynamodb": "^3.438.0", - "@aws-sdk/lib-dynamodb": "^3.438.0", + "@aws-sdk/client-dynamodb": "^3.525.0", + "@aws-sdk/lib-dynamodb": "^3.525.0", "@types/jmespath": "^0.15.0", - "aws-sdk-client-mock": "^3.0.0", - "aws-sdk-client-mock-jest": "^3.0.0" + "aws-sdk-client-mock": "^3.0.1", + "aws-sdk-client-mock-jest": "^3.0.1" }, "peerDependencies": { "@aws-sdk/client-dynamodb": ">=3.x", @@ -16731,15 +17278,15 @@ }, "packages/logger": { "name": "@aws-lambda-powertools/logger", - "version": "1.14.0", + "version": "2.0.2", "license": "MIT-0", "dependencies": { - "@aws-lambda-powertools/commons": "^1.14.0", + "@aws-lambda-powertools/commons": "^2.0.2", "lodash.merge": "^4.6.2" }, "devDependencies": { "@aws-lambda-powertools/testing-utils": "file:../testing", - "@types/lodash.merge": "^4.6.7" + "@types/lodash.merge": "^4.6.9" }, "peerDependencies": { "@middy/core": ">=3.x" @@ -16752,14 +17299,14 @@ }, "packages/metrics": { "name": "@aws-lambda-powertools/metrics", - "version": "1.14.0", + "version": "2.0.2", "license": "MIT-0", "dependencies": { - "@aws-lambda-powertools/commons": "^1.14.0" + "@aws-lambda-powertools/commons": "^2.0.2" }, "devDependencies": { "@aws-lambda-powertools/testing-utils": "file:../testing", - "@aws-sdk/client-cloudwatch": "^3.438.0", + "@aws-sdk/client-cloudwatch": "^3.525.0", "@types/promise-retry": "^1.1.3", "promise-retry": "^2.0.1" }, @@ -16774,21 +17321,21 @@ }, "packages/parameters": { "name": "@aws-lambda-powertools/parameters", - "version": "1.14.0", + "version": "2.0.2", "license": "MIT-0", "dependencies": { - "@aws-lambda-powertools/commons": "^1.14.0", + "@aws-lambda-powertools/commons": "^2.0.2", "@aws-sdk/util-base64-node": "^3.209.0" }, "devDependencies": { "@aws-lambda-powertools/testing-utils": "file:../testing", - "@aws-sdk/client-appconfigdata": "^3.438.0", - "@aws-sdk/client-dynamodb": "^3.438.0", - "@aws-sdk/client-secrets-manager": "^3.438.0", - "@aws-sdk/client-ssm": "^3.438.0", - "@aws-sdk/util-dynamodb": "^3.438.0", - "aws-sdk-client-mock": "^3.0.0", - "aws-sdk-client-mock-jest": "^3.0.0" + "@aws-sdk/client-appconfigdata": "^3.525.0", + "@aws-sdk/client-dynamodb": "^3.525.0", + "@aws-sdk/client-secrets-manager": "^3.525.0", + "@aws-sdk/client-ssm": "^3.525.0", + "@aws-sdk/util-dynamodb": "^3.525.0", + "aws-sdk-client-mock": "^3.0.1", + "aws-sdk-client-mock-jest": "^3.0.1" }, "peerDependencies": { "@aws-sdk/client-appconfigdata": ">=3.x", @@ -16820,7 +17367,6 @@ } }, "packages/parser": { - "name": "@aws-lambda-powertools/parser", "version": "0.0.0", "license": "MIT-0", "devDependencies": { @@ -16833,31 +17379,31 @@ }, "packages/testing": { "name": "@aws-lambda-powertools/testing-utils", - "version": "1.14.0", + "version": "2.0.2", "license": "MIT-0", "dependencies": { - "@aws-cdk/cli-lib-alpha": "^2.96.1-alpha.0", - "@aws-sdk/client-lambda": "^3.438.0", - "@smithy/util-utf8": "^2.0.0", - "aws-cdk-lib": "^2.96.1", - "esbuild": "^0.19.3" + "@aws-cdk/cli-lib-alpha": "^2.121.1-alpha.0", + "@aws-sdk/client-lambda": "^3.525.0", + "@smithy/util-utf8": "^2.1.0", + "aws-cdk-lib": "^2.130.0", + "esbuild": "^0.20.1" } }, "packages/tracer": { "name": "@aws-lambda-powertools/tracer", - "version": "1.14.0", + "version": "2.0.2", "license": "MIT-0", "dependencies": { - "@aws-lambda-powertools/commons": "^1.14.0", + "@aws-lambda-powertools/commons": "^2.0.2", "aws-xray-sdk-core": "^3.5.3" }, "devDependencies": { "@aws-lambda-powertools/testing-utils": "file:../testing", - "@aws-sdk/client-dynamodb": "^3.438.0", - "@aws-sdk/client-xray": "^3.438.0", - "@types/promise-retry": "^1.1.3", - "aws-sdk": "^2.1484.0", - "axios": "^1.6.0", + "@aws-sdk/client-dynamodb": "^3.525.0", + "@aws-sdk/client-xray": "^3.525.0", + "@types/promise-retry": "^1.1.6", + "aws-sdk": "^2.1568.0", + "axios": "^1.6.7", "promise-retry": "^2.0.1" }, "peerDependencies": { diff --git a/package.json b/package.json index 2d7f3e295c..a1ee943c05 100644 --- a/package.json +++ b/package.json @@ -18,13 +18,12 @@ "examples/sam" ], "scripts": { - "init-environment": "husky install", "test": "npm t -ws", "test:parallel": "lerna exec --no-bail --no-sort --stream --concurrency 8 -- npm run test", "test:e2e": "npm run test:e2e -ws", "test:e2e:parallel": "lerna exec --no-bail --no-sort --stream --concurrency 8 -- npm run test:e2e", "commit": "commit", - "setup-local": "npm ci && npm run build && npm run init-environment", + "setup-local": "npm ci && npm run build && husky", "build": "npm run build -ws", "docs-website-build-run": "npm run docs-buildDockerImage && npm run docs-runLocalDocker", "docs-buildDockerImage": "docker build -t powertools-typescript/docs ./docs/", @@ -49,33 +48,31 @@ }, "homepage": "https://github.com/aws-powertools/powertools-lambda-typescript#readme", "devDependencies": { - "@middy/core": "^4.6.5", - "@types/aws-lambda": "^8.10.121", - "@types/jest": "^29.5.4", - "@types/node": "^20.6.1", - "@types/uuid": "^9.0.4", - "@typescript-eslint/eslint-plugin": "^6.7.0", - "@typescript-eslint/parser": "^6.7.0", - "eslint": "^8.49.0", - "eslint-config-prettier": "^9.0.0", + "@middy/core": "^4.7.0", + "@types/aws-lambda": "^8.10.134", + "@types/jest": "^29.5.12", + "@types/node": "^20.11.24", + "@typescript-eslint/eslint-plugin": "^6.21.0", + "@typescript-eslint/parser": "^6.21.0", + "eslint": "^8.57.0", + "eslint-config-prettier": "^9.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-import-resolver-typescript": "^3.6.0", - "eslint-plugin-import": "^2.28.1", - "eslint-plugin-prettier": "^5.0.0", - "husky": "^8.0.3", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-prettier": "^5.1.3", + "husky": "^9.0.11", "jest": "^29.7.0", "jest-runner-groups": "^2.2.0", - "lerna": "^7.3.0", - "lint-staged": "^14.0.1", - "prettier": "^3.0.3", - "rimraf": "^5.0.1", - "ts-jest": "^29.1.1", - "ts-node": "^10.9.1", - "typedoc": "^0.25.1", - "typedoc-plugin-missing-exports": "^2.1.0", - "typescript": "^5.2.2" + "lerna": "^8.1.2", + "lint-staged": "^15.2.2", + "prettier": "^3.2.5", + "ts-jest": "^29.1.2", + "ts-node": "^10.9.2", + "typedoc": "^0.25.8", + "typedoc-plugin-missing-exports": "^2.2.0", + "typescript": "^5.3.3" }, "engines": { "node": ">=16" } -} \ No newline at end of file +} diff --git a/packages/batch/CHANGELOG.md b/packages/batch/CHANGELOG.md index 3599d4834c..1b05a4eb86 100644 --- a/packages/batch/CHANGELOG.md +++ b/packages/batch/CHANGELOG.md @@ -3,6 +3,65 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2.0.2 (2024-03-05) + + +**Note:** Version bump only for package @aws-lambda-powertools/batch + + + + + +## 2.0.1 (2024-03-04) + +**Note:** Version bump only for package @aws-lambda-powertools/batch + + + + + +# [2.0.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.18.1...v2.0.0) (2024-03-04) + +**Note:** Version bump only for package @aws-lambda-powertools/batch + + + + + +## 1.18.1 (2024-02-20) + +**Note:** Version bump only for package @aws-lambda-powertools/batch + + + + + +## [1.18.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.17.0...v1.18.0) (2024-01-26) + +**Note:** Version bump only for package @aws-lambda-powertools/batch + +## [1.17.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.16.0...v1.17.0) (2023-11-24) + +**maintenance:** drop support for Node.js 14 ([#1664](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1664)) ([e2a0923](https://github.com/aws-powertools/powertools-lambda-typescript/commit/e2a09232f86167b5208be2daf892aa1ea433ce0f)) + +# [1.16.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.15.0...v1.16.0) (2023-11-16) + +**Note:** Version bump only for package @aws-lambda-powertools/batch + +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) + +## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) + +**Note:** Version bump only for package @aws-lambda-powertools/batch + +## [1.14.1](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.0...v1.14.1) (2023-10-31) + +**Note:** Version bump only for package @aws-lambda-powertools/batch + # [1.14.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.13.1...v1.14.0) (2023-09-29) **Note:** Version bump only for package @aws-lambda-powertools/batch diff --git a/packages/batch/README.md b/packages/batch/README.md index 01885772c7..6807c77bde 100644 --- a/packages/batch/README.md +++ b/packages/batch/README.md @@ -240,6 +240,8 @@ The following companies, among others, use Powertools: * [Sennder](https://sennder.com/) * [Certible](https://www.certible.com/) * [tecRacer GmbH & Co. KG](https://www.tecracer.com/) +* [AppYourself](https://appyourself.net) +* [Alma Media](https://www.almamedia.fi) ### Sharing your work diff --git a/packages/batch/package.json b/packages/batch/package.json index 224d0e17d5..3495a7cf08 100644 --- a/packages/batch/package.json +++ b/packages/batch/package.json @@ -1,6 +1,6 @@ { "name": "@aws-lambda-powertools/batch", - "version": "1.14.0", + "version": "2.0.2", "description": "The batch processing package for the Powertools for AWS Lambda (TypeScript) library.", "author": { "name": "Amazon Web Services", @@ -15,6 +15,7 @@ "jest": "jest --detectOpenHandles --verbose", "test:e2e:nodejs16x": "echo 'Not Implemented'", "test:e2e:nodejs18x": "echo 'Not Implemented'", + "test:e2e:nodejs20x": "echo 'Not Implemented'", "test:e2e": "echo 'Not Implemented'", "watch": "jest --watch", "build:cjs": "tsc --build tsconfig.json && echo '{ \"type\": \"commonjs\" }' > lib/cjs/package.json", diff --git a/packages/batch/tests/helpers/populateEnvironmentVariables.ts b/packages/batch/tests/helpers/populateEnvironmentVariables.ts index cb0b37f295..9dc602e5f0 100644 --- a/packages/batch/tests/helpers/populateEnvironmentVariables.ts +++ b/packages/batch/tests/helpers/populateEnvironmentVariables.ts @@ -1,7 +1,7 @@ // Reserved variables process.env._X_AMZN_TRACE_ID = '1-abcdef12-3456abcdef123456abcdef12'; process.env.AWS_LAMBDA_FUNCTION_NAME = 'my-lambda-function'; -process.env.AWS_EXECUTION_ENV = 'nodejs18.x'; +process.env.AWS_EXECUTION_ENV = 'nodejs20.x'; process.env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = '128'; if ( process.env.AWS_REGION === undefined && diff --git a/packages/commons/CHANGELOG.md b/packages/commons/CHANGELOG.md index 147c277ff8..0284df207a 100644 --- a/packages/commons/CHANGELOG.md +++ b/packages/commons/CHANGELOG.md @@ -3,6 +3,65 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2.0.2 (2024-03-05) + +**Note:** Version bump only for package @aws-lambda-powertools/commons + + + + + +## 2.0.1 (2024-03-04) + +**Note:** Version bump only for package @aws-lambda-powertools/commons + + + + + +# [2.0.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.18.1...v2.0.0) (2024-03-04) + +**Note:** Version bump only for package @aws-lambda-powertools/commons + + + + + +## 1.18.1 (2024-02-20) + +**Note:** Version bump only for package @aws-lambda-powertools/commons + + + + + +## [1.18.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.17.0...v1.18.0) (2024-01-26) + +**Note:** Version bump only for package @aws-lambda-powertools/commons + +## [1.17.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.16.0...v1.17.0) (2023-11-24) + +**maintenance:** drop support for Node.js 14 ([#1664](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1664)) ([e2a0923](https://github.com/aws-powertools/powertools-lambda-typescript/commit/e2a09232f86167b5208be2daf892aa1ea433ce0f)) + +# [1.16.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.15.0...v1.16.0) (2023-11-16) + +**Note:** Version bump only for package @aws-lambda-powertools/commons + +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) +- **metrics:** log directly to stdout ([#1786](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1786)) ([75dc5b1](https://github.com/aws-powertools/powertools-lambda-typescript/commit/75dc5b1e16944416a287628c50ec4a0cf82c3023)) + +## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) + +**Note:** Version bump only for package @aws-lambda-powertools/commons + +## [1.14.1](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.0...v1.14.1) (2023-10-31) + +**Note:** Version bump only for package @aws-lambda-powertools/commons + # [1.14.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.13.1...v1.14.0) (2023-09-29) **Note:** Version bump only for package @aws-lambda-powertools/commons diff --git a/packages/commons/README.md b/packages/commons/README.md index 55290ccdd2..6a8f627f81 100644 --- a/packages/commons/README.md +++ b/packages/commons/README.md @@ -15,7 +15,7 @@ You can use the library in both TypeScript and JavaScript code bases. - [Getting started](#getting-started) - [Installation](#installation) - [Examples](#examples) - - [Serverless TypeScript Demo application](#serverless-typescript-demo-application) + - [Demo applications](#demo-applications) - [Contribute](#contribute) - [Roadmap](#roadmap) - [Connect](#connect) @@ -66,11 +66,13 @@ Or refer to the installation guide of each utility: * [CDK](https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/examples/cdk) * [SAM](https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/examples/sam) -### Serverless TypeScript Demo application +### Demo applications The [Serverless TypeScript Demo](https://github.com/aws-samples/serverless-typescript-demo) shows how to use Powertools for AWS Lambda (TypeScript). You can find instructions on how to deploy and load test this application in the [repository](https://github.com/aws-samples/serverless-typescript-demo). +The [AWS Lambda performance tuning](https://github.com/aws-samples/optimizations-for-lambda-functions) repository also uses Powertools for AWS Lambda (TypeScript) as well as demonstrating other performance tuning techniques for Lambda functions written in TypeScript. + ## Contribute If you are interested in contributing to this project, please refer to our [Contributing Guidelines](https://github.com/aws-powertools/powertools-lambda-typescript/blob/main/CONTRIBUTING.md). @@ -102,6 +104,8 @@ The following companies, among others, use Powertools: * [Sennder](https://sennder.com/) * [Certible](https://www.certible.com/) * [tecRacer GmbH & Co. KG](https://www.tecracer.com/) +* [AppYourself](https://appyourself.net) +* [Alma Media](https://www.almamedia.fi) ### Sharing your work diff --git a/packages/commons/package.json b/packages/commons/package.json index 508c45dbd3..aac76fecea 100644 --- a/packages/commons/package.json +++ b/packages/commons/package.json @@ -1,6 +1,6 @@ { "name": "@aws-lambda-powertools/commons", - "version": "1.14.0", + "version": "2.0.2", "description": "A shared utility package for Powertools for AWS Lambda (TypeScript) libraries", "author": { "name": "Amazon Web Services", diff --git a/packages/commons/src/awsSdkUtils.ts b/packages/commons/src/awsSdkUtils.ts index 519ee92619..29095c3d37 100644 --- a/packages/commons/src/awsSdkUtils.ts +++ b/packages/commons/src/awsSdkUtils.ts @@ -43,9 +43,8 @@ const customUserAgentMiddleware = (feature: string) => { return (next: (arg0: T) => Promise) => async (args: T) => { const powertoolsUserAgent = `PT/${feature}/${PT_VERSION} PTEnv/${EXEC_ENV}`; - args.request.headers[ - 'user-agent' - ] = `${args.request.headers['user-agent']} ${powertoolsUserAgent}`; + args.request.headers['user-agent'] = + `${args.request.headers['user-agent']} ${powertoolsUserAgent}`; return await next(args); }; diff --git a/packages/commons/src/config/EnvironmentVariablesService.ts b/packages/commons/src/config/EnvironmentVariablesService.ts index 485dbb21f4..599f4c88d1 100644 --- a/packages/commons/src/config/EnvironmentVariablesService.ts +++ b/packages/commons/src/config/EnvironmentVariablesService.ts @@ -1,4 +1,4 @@ -import { ConfigService } from './ConfigService.js'; +import type { ConfigServiceInterface } from '../types/ConfigServiceInterface.js'; /** * Class EnvironmentVariablesService @@ -13,11 +13,12 @@ import { ConfigService } from './ConfigService.js'; * @see https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime * @see https://docs.powertools.aws.dev/lambda/typescript/latest/#environment-variables */ -class EnvironmentVariablesService extends ConfigService { +class EnvironmentVariablesService implements ConfigServiceInterface { /** * @see https://docs.powertools.aws.dev/lambda/typescript/latest/#environment-variables * @protected */ + protected devModeVariable = 'POWERTOOLS_DEV'; protected serviceNameVariable = 'POWERTOOLS_SERVICE_NAME'; // Reserved environment variables private xRayTraceIdVariable = '_X_AMZN_TRACE_ID'; @@ -71,6 +72,15 @@ class EnvironmentVariablesService extends ConfigService { return xRayTraceData?.Sampled === '1'; } + /** + * It returns true if the `POWERTOOLS_DEV` environment variable is set to truthy value. + * + * @returns {boolean} + */ + public isDevMode(): boolean { + return this.isValueTrue(this.get(this.devModeVariable)); + } + /** * It returns true if the string value represents a boolean true value. * diff --git a/packages/commons/src/config/ConfigService.ts b/packages/commons/src/types/ConfigServiceInterface.ts similarity index 71% rename from packages/commons/src/config/ConfigService.ts rename to packages/commons/src/types/ConfigServiceInterface.ts index e149c27229..1e249f9373 100644 --- a/packages/commons/src/config/ConfigService.ts +++ b/packages/commons/src/types/ConfigServiceInterface.ts @@ -3,25 +3,22 @@ * * This class defines common methods and variables that can be set by the developer * in the runtime. - * - * @class - * @abstract */ -abstract class ConfigService { +interface ConfigServiceInterface { /** * It returns the value of an environment variable that has given name. * * @param {string} name * @returns {string} */ - public abstract get(name: string): string; + get(name: string): string; /** * It returns the value of the POWERTOOLS_SERVICE_NAME environment variable. * * @returns {string} */ - public abstract getServiceName(): string; + getServiceName(): string; /** * It returns the value of the _X_AMZN_TRACE_ID environment variable. @@ -33,7 +30,14 @@ abstract class ConfigService { * * @returns {string|undefined} */ - public abstract getXrayTraceId(): string | undefined; + getXrayTraceId(): string | undefined; + + /** + * It returns true if the `POWERTOOLS_DEV` environment variable is set to truthy value. + * + * @returns {boolean} + */ + isDevMode(): boolean; /** * It returns true if the string value represents a boolean true value. @@ -41,7 +45,7 @@ abstract class ConfigService { * @param {string} value * @returns boolean */ - public abstract isValueTrue(value: string): boolean; + isValueTrue(value: string): boolean; } -export { ConfigService }; +export type { ConfigServiceInterface }; diff --git a/packages/commons/src/types/index.ts b/packages/commons/src/types/index.ts index 068a9225e3..b57b2dfec4 100644 --- a/packages/commons/src/types/index.ts +++ b/packages/commons/src/types/index.ts @@ -16,3 +16,4 @@ export type { LambdaInterface, HandlerMethodDecorator, } from './LambdaInterface.js'; +export type { ConfigServiceInterface } from './ConfigServiceInterface.js'; diff --git a/packages/commons/src/version.ts b/packages/commons/src/version.ts index c42c660c40..a4e5b97746 100644 --- a/packages/commons/src/version.ts +++ b/packages/commons/src/version.ts @@ -1,2 +1,2 @@ // this file is auto generated, do not modify -export const PT_VERSION = '1.13.1'; +export const PT_VERSION = '2.0.2'; diff --git a/packages/commons/tests/unit/EnvironmentVariablesService.test.ts b/packages/commons/tests/unit/EnvironmentVariablesService.test.ts index c7b4c75d19..230e04afb0 100644 --- a/packages/commons/tests/unit/EnvironmentVariablesService.test.ts +++ b/packages/commons/tests/unit/EnvironmentVariablesService.test.ts @@ -162,4 +162,54 @@ describe('Class: EnvironmentVariablesService', () => { } ); }); + + describe('Method: isDevMode', () => { + test('it returns true if the environment variable POWERTOOLS_DEV is "true"', () => { + // Prepare + process.env.POWERTOOLS_DEV = 'true'; + const service = new EnvironmentVariablesService(); + + // Act + const value = service.isDevMode(); + + // Assess + expect(value).toEqual(true); + }); + + test('it returns false if the environment variable POWERTOOLS_DEV is "false"', () => { + // Prepare + process.env.POWERTOOLS_DEV = 'false'; + const service = new EnvironmentVariablesService(); + + // Act + const value = service.isDevMode(); + + // Assess + expect(value).toEqual(false); + }); + + test('it returns false if the environment variable POWERTOOLS_DEV is NOT set', () => { + // Prepare + process.env.POWERTOOLS_DEV = 'somethingsilly'; + const service = new EnvironmentVariablesService(); + + // Act + const value = service.isDevMode(); + + // Assess + expect(value).toEqual(false); + }); + + test('it returns false if the environment variable POWERTOOLS_DEV is "somethingsilly"', () => { + // Prepare + process.env.POWERTOOLS_DEV = 'somethingsilly'; + const service = new EnvironmentVariablesService(); + + // Act + const value = service.isDevMode(); + + // Assess + expect(value).toEqual(false); + }); + }); }); diff --git a/packages/idempotency/CHANGELOG.md b/packages/idempotency/CHANGELOG.md index cb5cb21a55..3a72cdc5be 100644 --- a/packages/idempotency/CHANGELOG.md +++ b/packages/idempotency/CHANGELOG.md @@ -3,6 +3,66 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2.0.2 (2024-03-05) + +**Note:** Version bump only for package @aws-lambda-powertools/idempotency + + + + + +## 2.0.1 (2024-03-04) + +**Note:** Version bump only for package @aws-lambda-powertools/idempotency + + + + + +# [2.0.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.18.1...v2.0.0) (2024-03-04) + +**Note:** Version bump only for package @aws-lambda-powertools/idempotency + + + + + +## 1.18.1 (2024-02-20) + +**Note:** Version bump only for package @aws-lambda-powertools/idempotency + + + + + +## [1.18.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.17.0...v1.18.0) (2024-01-26) + +### Features + +- **idempotency:** leverage new DynamoDB failed conditional writes ([#1779](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1779)) ([1917ec6](https://github.com/aws-powertools/powertools-lambda-typescript/commit/1917ec6b48df17de3126a1b8b1d008295e60f4ef)) + +## [1.17.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.16.0...v1.17.0) (2023-11-24) + +**maintenance:** drop support for Node.js 14 ([#1664](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1664)) ([e2a0923](https://github.com/aws-powertools/powertools-lambda-typescript/commit/e2a09232f86167b5208be2daf892aa1ea433ce0f)) + +# [1.16.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.15.0...v1.16.0) (2023-11-16) + +**Note:** Version bump only for package @aws-lambda-powertools/idempotency + +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) + +## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) + +**Note:** Version bump only for package @aws-lambda-powertools/idempotency + +## [1.14.1](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.0...v1.14.1) (2023-10-31) + +**Note:** Version bump only for package @aws-lambda-powertools/idempotency + # [1.14.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.13.1...v1.14.0) (2023-09-29) ### Features diff --git a/packages/idempotency/README.md b/packages/idempotency/README.md index 70b8f504b4..6d8edd7061 100644 --- a/packages/idempotency/README.md +++ b/packages/idempotency/README.md @@ -302,6 +302,8 @@ The following companies, among others, use Powertools: * [Sennder](https://sennder.com/) * [Certible](https://www.certible.com/) * [tecRacer GmbH & Co. KG](https://www.tecracer.com/) +* [AppYourself](https://appyourself.net) +* [Alma Media](https://www.almamedia.fi) ### Sharing your work diff --git a/packages/idempotency/package.json b/packages/idempotency/package.json index 1fdf31ee32..5984549a7d 100644 --- a/packages/idempotency/package.json +++ b/packages/idempotency/package.json @@ -1,6 +1,6 @@ { "name": "@aws-lambda-powertools/idempotency", - "version": "1.14.0", + "version": "2.0.2", "description": "The idempotency package for the Powertools for AWS Lambda (TypeScript) library. It provides options to make your Lambda functions idempotent and safe to retry.", "author": { "name": "Amazon Web Services", @@ -15,6 +15,7 @@ "jest": "jest --detectOpenHandles --verbose", "test:e2e:nodejs16x": "RUNTIME=nodejs16x jest --group=e2e", "test:e2e:nodejs18x": "RUNTIME=nodejs18x jest --group=e2e", + "test:e2e:nodejs20x": "RUNTIME=nodejs20x jest --group=e2e", "test:e2e": "jest --group=e2e", "watch": "jest --watch", "build:cjs": "tsc --build tsconfig.json && echo '{ \"type\": \"commonjs\" }' > lib/cjs/package.json", @@ -99,7 +100,7 @@ "url": "https://github.com/aws-powertools/powertools-lambda-typescript/issues" }, "dependencies": { - "@aws-lambda-powertools/commons": "^1.14.0", + "@aws-lambda-powertools/commons": "^2.0.2", "@aws-sdk/util-base64-node": "^3.209.0", "jmespath": "^0.16.0" }, @@ -129,10 +130,10 @@ ], "devDependencies": { "@aws-lambda-powertools/testing-utils": "file:../testing", - "@aws-sdk/client-dynamodb": "^3.438.0", - "@aws-sdk/lib-dynamodb": "^3.438.0", + "@aws-sdk/client-dynamodb": "^3.525.0", + "@aws-sdk/lib-dynamodb": "^3.525.0", "@types/jmespath": "^0.15.0", - "aws-sdk-client-mock": "^3.0.0", - "aws-sdk-client-mock-jest": "^3.0.0" + "aws-sdk-client-mock": "^3.0.1", + "aws-sdk-client-mock-jest": "^3.0.1" } } diff --git a/packages/idempotency/src/IdempotencyHandler.ts b/packages/idempotency/src/IdempotencyHandler.ts index bc52c5d904..03f06b1c2d 100644 --- a/packages/idempotency/src/IdempotencyHandler.ts +++ b/packages/idempotency/src/IdempotencyHandler.ts @@ -304,9 +304,10 @@ export class IdempotencyHandler { }; /** - * Save an in progress record to the idempotency store or return an existing result. + * Save an in progress record to the idempotency store or return an stored result. * - * If the record already exists, return the result from the record. + * Before returning a result, we might neede to look up the idempotency record + * and validate it to ensure that it is consistent with the payload to be hashed. */ #saveInProgressOrReturnExistingResult = async (): Promise => { @@ -317,10 +318,22 @@ export class IdempotencyHandler { ); } catch (e) { if (e instanceof IdempotencyItemAlreadyExistsError) { - const idempotencyRecord: IdempotencyRecord = - await this.#persistenceStore.getRecord( + let idempotencyRecord = e.existingRecord; + if (idempotencyRecord !== undefined) { + // If the error includes the existing record, we can use it to validate + // the record being processed and cache it in memory. + idempotencyRecord = this.#persistenceStore.processExistingRecord( + idempotencyRecord, this.#functionPayloadToBeHashed ); + // If the error doesn't include the existing record, we need to fetch + // it from the persistence layer. In doing so, we also call the processExistingRecord + // method to validate the record and cache it in memory. + } else { + idempotencyRecord = await this.#persistenceStore.getRecord( + this.#functionPayloadToBeHashed + ); + } return IdempotencyHandler.determineResultFromIdempotencyRecord( idempotencyRecord diff --git a/packages/idempotency/src/errors.ts b/packages/idempotency/src/errors.ts index da96692bc8..5f210adfcd 100644 --- a/packages/idempotency/src/errors.ts +++ b/packages/idempotency/src/errors.ts @@ -1,7 +1,16 @@ +import type { IdempotencyRecord } from './persistence/IdempotencyRecord.js'; + /** * Item attempting to be inserted into persistence store already exists and is not expired */ -class IdempotencyItemAlreadyExistsError extends Error {} +class IdempotencyItemAlreadyExistsError extends Error { + public existingRecord?: IdempotencyRecord; + + public constructor(message?: string, existingRecord?: IdempotencyRecord) { + super(message); + this.existingRecord = existingRecord; + } +} /** * Item does not exist in persistence store @@ -21,7 +30,14 @@ class IdempotencyInvalidStatusError extends Error {} /** * Payload does not match stored idempotency record */ -class IdempotencyValidationError extends Error {} +class IdempotencyValidationError extends Error { + public existingRecord?: IdempotencyRecord; + + public constructor(message?: string, existingRecord?: IdempotencyRecord) { + super(message); + this.existingRecord = existingRecord; + } +} /** * State is inconsistent across multiple requests to persistence store diff --git a/packages/idempotency/src/idempotencyDecorator.ts b/packages/idempotency/src/idempotencyDecorator.ts index e912393a85..6c6ff7b2e1 100644 --- a/packages/idempotency/src/idempotencyDecorator.ts +++ b/packages/idempotency/src/idempotencyDecorator.ts @@ -15,7 +15,7 @@ import { makeIdempotent } from './makeIdempotent.js'; * DynamoDBPersistenceLayer, * idempotentLambdaHandler * } from '@aws-lambda-powertools/idempotency'; - * import type { LambdaInterface } from '@aws-lambda-powertools/commons'; + * import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; * * class MyLambdaFunction implements LambdaInterface { * ⁣@idempotent({ persistenceStore: new DynamoDBPersistenceLayer() }) @@ -34,7 +34,7 @@ import { makeIdempotent } from './makeIdempotent.js'; * DynamoDBPersistenceLayer, * idempotentFunction * } from '@aws-lambda-powertools/idempotency'; - * import type { LambdaInterface } from '@aws-lambda-powertools/commons'; + * import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; * * class MyClass implements LambdaInterface { * public async handler(event: unknown, _context: unknown) { diff --git a/packages/idempotency/src/persistence/BasePersistenceLayer.ts b/packages/idempotency/src/persistence/BasePersistenceLayer.ts index afd448d6d1..526f963378 100644 --- a/packages/idempotency/src/persistence/BasePersistenceLayer.ts +++ b/packages/idempotency/src/persistence/BasePersistenceLayer.ts @@ -117,8 +117,7 @@ abstract class BasePersistenceLayer implements BasePersistenceLayerInterface { } const record = await this._getRecord(idempotencyKey); - this.saveToCache(record); - this.validatePayload(data, record); + this.processExistingRecord(record, data); return record; } @@ -130,6 +129,29 @@ abstract class BasePersistenceLayer implements BasePersistenceLayerInterface { return this.payloadValidationEnabled; } + /** + * Validates an existing record against the data payload being processed. + * If the payload does not match the stored record, an `IdempotencyValidationError` error is thrown. + * + * Whenever a record is retrieved from the persistence layer, it should be validated against the data payload + * being processed. This is to ensure that the data payload being processed is the same as the one that was + * used to create the record in the first place. + * + * The record is also saved to the local cache if local caching is enabled. + * + * @param record - the stored record to validate against + * @param data - the data payload being processed and to be validated against the stored record + */ + public processExistingRecord( + storedDataRecord: IdempotencyRecord, + processedData: JSONValue | IdempotencyRecord + ): IdempotencyRecord { + this.validatePayload(processedData, storedDataRecord); + this.saveToCache(storedDataRecord); + + return storedDataRecord; + } + /** * Saves a record indicating that the function's execution is currently in progress * @@ -157,7 +179,10 @@ abstract class BasePersistenceLayer implements BasePersistenceLayerInterface { } if (this.getFromCache(idempotencyRecord.idempotencyKey)) { - throw new IdempotencyItemAlreadyExistsError(); + throw new IdempotencyItemAlreadyExistsError( + `Failed to put record for already existing idempotency key: ${idempotencyRecord.idempotencyKey}`, + idempotencyRecord + ); } await this._putRecord(idempotencyRecord); @@ -305,8 +330,9 @@ abstract class BasePersistenceLayer implements BasePersistenceLayerInterface { /** * Save record to local cache except for when status is `INPROGRESS`. * - * We can't cache `INPROGRESS` records because we have no way to reflect updates - * that might happen to the record outside the execution context of the function. + * Records with `INPROGRESS` status are not cached because we have no way to + * reflect updates that might happen to the record outside the execution + * context of the function. * * @param record - record to save */ @@ -316,12 +342,26 @@ abstract class BasePersistenceLayer implements BasePersistenceLayerInterface { this.cache?.add(record.idempotencyKey, record); } - private validatePayload(data: JSONValue, record: IdempotencyRecord): void { + /** + * Validates the payload against the stored record. If the payload does not match the stored record, + * an `IdempotencyValidationError` error is thrown. + * + * @param data - The data payload to validate against the stored record + * @param storedDataRecord - The stored record to validate against + */ + private validatePayload( + data: JSONValue | IdempotencyRecord, + storedDataRecord: IdempotencyRecord + ): void { if (this.payloadValidationEnabled) { - const hashedPayload: string = this.getHashedPayload(data); - if (hashedPayload !== record.payloadHash) { + const hashedPayload = + data instanceof IdempotencyRecord + ? data.payloadHash + : this.getHashedPayload(data); + if (hashedPayload !== storedDataRecord.payloadHash) { throw new IdempotencyValidationError( - 'Payload does not match stored record for this event key' + 'Payload does not match stored record for this event key', + storedDataRecord ); } } diff --git a/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts b/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts index 32b55777e4..eacbe47e0a 100644 --- a/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts +++ b/packages/idempotency/src/persistence/DynamoDBPersistenceLayer.ts @@ -6,10 +6,10 @@ import { IdempotencyRecordStatus } from '../constants.js'; import type { DynamoDBPersistenceOptions } from '../types/DynamoDBPersistence.js'; import { AttributeValue, + ConditionalCheckFailedException, DeleteItemCommand, DynamoDBClient, DynamoDBClientConfig, - DynamoDBServiceException, GetItemCommand, PutItemCommand, UpdateItemCommand, @@ -198,15 +198,26 @@ class DynamoDBPersistenceLayer extends BasePersistenceLayer { ':inprogress': IdempotencyRecordStatus.INPROGRESS, }), ConditionExpression: conditionExpression, + ReturnValuesOnConditionCheckFailure: 'ALL_OLD', }) ); } catch (error) { - if (error instanceof DynamoDBServiceException) { - if (error.name === 'ConditionalCheckFailedException') { - throw new IdempotencyItemAlreadyExistsError( - `Failed to put record for already existing idempotency key: ${record.idempotencyKey}` - ); - } + if (error instanceof ConditionalCheckFailedException) { + const item = error.Item && unmarshall(error.Item); + const idempotencyRecord = + item && + new IdempotencyRecord({ + idempotencyKey: item[this.keyAttr], + status: item[this.statusAttr], + expiryTimestamp: item[this.expiryAttr], + inProgressExpiryTimestamp: item[this.inProgressExpiryAttr], + responseData: item[this.dataAttr], + payloadHash: item[this.validationKeyAttr], + }); + throw new IdempotencyItemAlreadyExistsError( + `Failed to put record for already existing idempotency key: ${record.idempotencyKey}`, + idempotencyRecord + ); } throw error; diff --git a/packages/idempotency/src/types/ConfigServiceInterface.ts b/packages/idempotency/src/types/ConfigServiceInterface.ts index eaa36e8e1f..c4d8f11b25 100644 --- a/packages/idempotency/src/types/ConfigServiceInterface.ts +++ b/packages/idempotency/src/types/ConfigServiceInterface.ts @@ -1,10 +1,27 @@ -interface ConfigServiceInterface { - get(name: string): string; - - getServiceName(): string; +import type { ConfigServiceInterface as ConfigServiceBaseInterface } from '@aws-lambda-powertools/commons/types'; +/** + * Interface ConfigServiceInterface + * + * @interface + * @see https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime + * @see https://docs.powertools.aws.dev/lambda/typescript/latest/#environment-variables + */ +interface ConfigServiceInterface extends ConfigServiceBaseInterface { + /** + * It returns the value of the AWS_LAMBDA_FUNCTION_NAME environment variable. + * + * @returns {string} + */ getFunctionName(): string; + /** + * It returns whether the idempotency feature is enabled or not. + * + * Reads the value of the POWERTOOLS_IDEMPOTENCY_DISABLED environment variable. + * + * @returns {boolean} + */ getIdempotencyEnabled(): boolean; } diff --git a/packages/idempotency/tests/e2e/constants.ts b/packages/idempotency/tests/e2e/constants.ts index 53cb30860f..38ae9b6c83 100644 --- a/packages/idempotency/tests/e2e/constants.ts +++ b/packages/idempotency/tests/e2e/constants.ts @@ -2,5 +2,5 @@ export const RESOURCE_NAME_PREFIX = 'Idempotency'; export const ONE_MINUTE = 60 * 1_000; export const TEARDOWN_TIMEOUT = 5 * ONE_MINUTE; -export const SETUP_TIMEOUT = 5 * ONE_MINUTE; +export const SETUP_TIMEOUT = 7 * ONE_MINUTE; export const TEST_CASE_TIMEOUT = 5 * ONE_MINUTE; diff --git a/packages/idempotency/tests/unit/IdempotencyHandler.test.ts b/packages/idempotency/tests/unit/IdempotencyHandler.test.ts index 174b63acaa..d9e4e0deb7 100644 --- a/packages/idempotency/tests/unit/IdempotencyHandler.test.ts +++ b/packages/idempotency/tests/unit/IdempotencyHandler.test.ts @@ -119,6 +119,28 @@ describe('Class IdempotencyHandler', () => { expect(saveInProgressSpy).toHaveBeenCalledTimes(1); }); + test('when IdempotencyAlreadyInProgressError is thrown and it contains the existing item, it returns it directly', async () => { + // Prepare + const saveInProgressSpy = jest + .spyOn(persistenceStore, 'saveInProgress') + .mockRejectedValueOnce( + new IdempotencyItemAlreadyExistsError( + 'Failed to put record for already existing idempotency key: idempotence-key', + new IdempotencyRecord({ + idempotencyKey: 'key', + status: IdempotencyRecordStatus.COMPLETED, + responseData: 'Hi', + }) + ) + ); + const getRecordSpy = jest.spyOn(persistenceStore, 'getRecord'); + + // Act & Assess + await expect(idempotentHandler.handle()).resolves.toEqual('Hi'); + expect(saveInProgressSpy).toHaveBeenCalledTimes(1); + expect(getRecordSpy).toHaveBeenCalledTimes(0); + }); + test('when IdempotencyInconsistentStateError is thrown, it retries until max retries are exhausted', async () => { // Prepare const mockProcessIdempotency = jest diff --git a/packages/idempotency/tests/unit/idempotencyDecorator.test.ts b/packages/idempotency/tests/unit/idempotencyDecorator.test.ts index 0ff10d1894..ebd8caacd6 100644 --- a/packages/idempotency/tests/unit/idempotencyDecorator.test.ts +++ b/packages/idempotency/tests/unit/idempotencyDecorator.test.ts @@ -3,7 +3,6 @@ * * @group unit/idempotency/decorator */ - import { BasePersistenceLayer, IdempotencyRecord, @@ -46,7 +45,10 @@ class TestinClassWithLambdaHandler { @idempotent({ persistenceStore: new PersistenceLayerTestClass(), }) - public testing(record: Record, _context: Context): string { + public async testing( + record: Record, + _context: Context + ): Promise { functionalityToDecorate(record); return 'Hi'; @@ -54,7 +56,10 @@ class TestinClassWithLambdaHandler { } class TestingClassWithFunctionDecorator { - public handler(record: Record, context: Context): string { + public async handler( + record: Record, + context: Context + ): Promise { mockConfig.registerLambdaContext(context); return this.proccessRecord(record, 'bar'); @@ -65,7 +70,10 @@ class TestingClassWithFunctionDecorator { config: mockConfig, dataIndexArgument: 0, }) - public proccessRecord(record: Record, _foo: string): string { + public async proccessRecord( + record: Record, + _foo: string + ): Promise { functionalityToDecorate(record); return 'Processed Record'; @@ -86,18 +94,21 @@ describe('Given a class with a function to decorate', (classWithLambdaHandler = }); test('Then it will save the record to INPROGRESS', () => { - expect(mockSaveInProgress).toBeCalledWith( + expect(mockSaveInProgress).toHaveBeenCalledWith( inputRecord, context.getRemainingTimeInMillis() ); }); test('Then it will call the function that was decorated', () => { - expect(functionalityToDecorate).toBeCalledWith(inputRecord); + expect(functionalityToDecorate).toHaveBeenCalledWith(inputRecord); }); test('Then it will save the record to COMPLETED with function return value', () => { - expect(mockSaveSuccess).toBeCalledWith(inputRecord, 'Processed Record'); + expect(mockSaveSuccess).toHaveBeenCalledWith( + inputRecord, + 'Processed Record' + ); }); }); describe('When wrapping a handler function with no previous executions', () => { @@ -106,18 +117,18 @@ describe('Given a class with a function to decorate', (classWithLambdaHandler = }); test('Then it will save the record to INPROGRESS', () => { - expect(mockSaveInProgress).toBeCalledWith( + expect(mockSaveInProgress).toHaveBeenCalledWith( inputRecord, context.getRemainingTimeInMillis() ); }); test('Then it will call the function that was decorated', () => { - expect(functionalityToDecorate).toBeCalledWith(inputRecord); + expect(functionalityToDecorate).toHaveBeenCalledWith(inputRecord); }); test('Then it will save the record to COMPLETED with function return value', () => { - expect(mockSaveSuccess).toBeCalledWith(inputRecord, 'Hi'); + expect(mockSaveSuccess).toHaveBeenCalledWith(inputRecord, 'Hi'); }); }); @@ -142,18 +153,18 @@ describe('Given a class with a function to decorate', (classWithLambdaHandler = }); test('Then it will attempt to save the record to INPROGRESS', () => { - expect(mockSaveInProgress).toBeCalledWith( + expect(mockSaveInProgress).toHaveBeenCalledWith( inputRecord, context.getRemainingTimeInMillis() ); }); test('Then it will get the previous execution record', () => { - expect(mockGetRecord).toBeCalledWith(inputRecord); + expect(mockGetRecord).toHaveBeenCalledWith(inputRecord); }); test('Then it will not call the function that was decorated', () => { - expect(functionalityToDecorate).not.toBeCalled(); + expect(functionalityToDecorate).not.toHaveBeenCalled(); }); test('Then an IdempotencyAlreadyInProgressError is thrown', () => { @@ -182,18 +193,18 @@ describe('Given a class with a function to decorate', (classWithLambdaHandler = }); test('Then it will attempt to save the record to INPROGRESS', () => { - expect(mockSaveInProgress).toBeCalledWith( + expect(mockSaveInProgress).toHaveBeenCalledWith( inputRecord, context.getRemainingTimeInMillis() ); }); test('Then it will get the previous execution record', () => { - expect(mockGetRecord).toBeCalledWith(inputRecord); + expect(mockGetRecord).toHaveBeenCalledWith(inputRecord); }); test('Then it will not call the function that was decorated', () => { - expect(functionalityToDecorate).not.toBeCalled(); + expect(functionalityToDecorate).not.toHaveBeenCalled(); }); test('Then an IdempotencyInconsistentStateError is thrown', () => { @@ -219,18 +230,18 @@ describe('Given a class with a function to decorate', (classWithLambdaHandler = }); test('Then it will attempt to save the record to INPROGRESS', () => { - expect(mockSaveInProgress).toBeCalledWith( + expect(mockSaveInProgress).toHaveBeenCalledWith( inputRecord, context.getRemainingTimeInMillis() ); }); test('Then it will get the previous execution record', () => { - expect(mockGetRecord).toBeCalledWith(inputRecord); + expect(mockGetRecord).toHaveBeenCalledWith(inputRecord); }); test('Then it will not call decorated functionality', () => { - expect(functionalityToDecorate).not.toBeCalledWith(inputRecord); + expect(functionalityToDecorate).not.toHaveBeenCalledWith(inputRecord); }); }); @@ -260,7 +271,7 @@ describe('Given a class with a function to decorate', (classWithLambdaHandler = }); test('Then it will attempt to save the record to INPROGRESS', () => { - expect(mockSaveInProgress).toBeCalledWith( + expect(mockSaveInProgress).toHaveBeenCalledWith( inputRecord, context.getRemainingTimeInMillis() ); @@ -279,10 +290,10 @@ describe('Given a class with a function to decorate', (classWithLambdaHandler = persistenceStore: new PersistenceLayerTestClass(), config: new IdempotencyConfig({ lambdaContext: context }), }) - public testing( + public async testing( record: Record, _context: Context - ): string { + ): Promise { functionalityToDecorate(record); return 'Hi'; @@ -294,8 +305,8 @@ describe('Given a class with a function to decorate', (classWithLambdaHandler = }); test('Then it will skip ipdemotency', async () => { - expect(mockSaveInProgress).not.toBeCalled(); - expect(mockSaveSuccess).not.toBeCalled(); + expect(mockSaveInProgress).not.toHaveBeenCalled(); + expect(mockSaveSuccess).not.toHaveBeenCalled(); }); afterAll(() => { diff --git a/packages/idempotency/tests/unit/persistence/BasePersistenceLayer.test.ts b/packages/idempotency/tests/unit/persistence/BasePersistenceLayer.test.ts index 5417e9de02..a245a1f582 100644 --- a/packages/idempotency/tests/unit/persistence/BasePersistenceLayer.test.ts +++ b/packages/idempotency/tests/unit/persistence/BasePersistenceLayer.test.ts @@ -3,6 +3,7 @@ * * @group unit/idempotency/persistence/base */ +import { createHash } from 'node:crypto'; import context from '@aws-lambda-powertools/testing-utils/context'; import { IdempotencyConfig, @@ -244,18 +245,20 @@ describe('Class: BasePersistenceLayer', () => { payloadValidationJmesPath: 'foo', }), }); - jest.spyOn(persistenceLayer, '_getRecord').mockReturnValue( - new IdempotencyRecord({ - idempotencyKey: 'my-lambda-function#mocked-hash', - status: IdempotencyRecordStatus.INPROGRESS, - payloadHash: 'different-hash', - }) - ); + const existingRecord = new IdempotencyRecord({ + idempotencyKey: 'my-lambda-function#mocked-hash', + status: IdempotencyRecordStatus.INPROGRESS, + payloadHash: 'different-hash', + }); + jest + .spyOn(persistenceLayer, '_getRecord') + .mockReturnValue(existingRecord); // Act & Assess await expect(persistenceLayer.getRecord({ foo: 'bar' })).rejects.toThrow( new IdempotencyValidationError( - 'Payload does not match stored record for this event key' + 'Payload does not match stored record for this event key', + existingRecord ) ); }); @@ -410,7 +413,7 @@ describe('Class: BasePersistenceLayer', () => { // Act & Assess await expect( persistenceLayer.saveInProgress({ foo: 'bar' }) - ).rejects.toThrow(new IdempotencyItemAlreadyExistsError()); + ).rejects.toThrow(IdempotencyItemAlreadyExistsError); expect(putRecordSpy).toHaveBeenCalledTimes(0); }); @@ -465,6 +468,92 @@ describe('Class: BasePersistenceLayer', () => { }); }); + describe('Method: processExistingRecord', () => { + it('throws an error if the payload does not match the stored record', () => { + // Prepare + const persistenceLayer = new PersistenceLayerTestClass(); + persistenceLayer.configure({ + config: new IdempotencyConfig({ + payloadValidationJmesPath: 'foo', + }), + }); + const existingRecord = new IdempotencyRecord({ + idempotencyKey: 'my-lambda-function#mocked-hash', + status: IdempotencyRecordStatus.INPROGRESS, + payloadHash: 'different-hash', + }); + + // Act & Assess + expect(() => + persistenceLayer.processExistingRecord(existingRecord, { foo: 'bar' }) + ).toThrow( + new IdempotencyValidationError( + 'Payload does not match stored record for this event key', + existingRecord + ) + ); + }); + + it('returns if the payload matches the stored record', () => { + // Prepare + const persistenceLayer = new PersistenceLayerTestClass(); + persistenceLayer.configure({ + config: new IdempotencyConfig({ + payloadValidationJmesPath: 'foo', + }), + }); + const existingRecord = new IdempotencyRecord({ + idempotencyKey: 'my-lambda-function#mocked-hash', + status: IdempotencyRecordStatus.INPROGRESS, + payloadHash: 'mocked-hash', + }); + + // Act & Assess + expect(() => + persistenceLayer.processExistingRecord(existingRecord, { foo: 'bar' }) + ).not.toThrow(); + }); + + it('skips validation if payload validation is not enabled', () => { + // Prepare + const persistenceLayer = new PersistenceLayerTestClass(); + const existingRecord = new IdempotencyRecord({ + idempotencyKey: 'my-lambda-function#mocked-hash', + status: IdempotencyRecordStatus.INPROGRESS, + payloadHash: 'different-hash', + }); + + // Act & Assess + expect(() => + persistenceLayer.processExistingRecord(existingRecord, { foo: 'bar' }) + ).not.toThrow(); + }); + + it('skips hashing if the payload is already an IdempotencyRecord', () => { + // Prepare + const persistenceLayer = new PersistenceLayerTestClass(); + persistenceLayer.configure({ + config: new IdempotencyConfig({ + payloadValidationJmesPath: 'foo', + }), + }); + const existingRecord = new IdempotencyRecord({ + idempotencyKey: 'my-lambda-function#mocked-hash', + status: IdempotencyRecordStatus.INPROGRESS, + payloadHash: 'mocked-hash', + }); + const payload = new IdempotencyRecord({ + idempotencyKey: 'my-lambda-function#mocked-hash', + status: IdempotencyRecordStatus.INPROGRESS, + payloadHash: 'mocked-hash', + }); + + // Act + persistenceLayer.processExistingRecord(existingRecord, payload); + expect(createHash).toHaveBeenCalledTimes(0); + }); + }); + describe('Method: getExpiresAfterSeconds', () => { it('returns the configured value', () => { // Prepare diff --git a/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts b/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts index 3d75862728..29e8930161 100644 --- a/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts +++ b/packages/idempotency/tests/unit/persistence/DynamoDbPersistenceLayer.test.ts @@ -12,8 +12,8 @@ import { IdempotencyItemNotFoundError, } from '../../../src/index.js'; import { + ConditionalCheckFailedException, DynamoDBClient, - DynamoDBServiceException, PutItemCommand, GetItemCommand, UpdateItemCommand, @@ -395,19 +395,30 @@ describe('Class: DynamoDBPersistenceLayer', () => { expiryTimestamp: 0, }); client.on(PutItemCommand).rejects( - new DynamoDBServiceException({ - $fault: 'client', + new ConditionalCheckFailedException({ $metadata: { httpStatusCode: 400, requestId: 'someRequestId', }, - name: 'ConditionalCheckFailedException', + message: 'Conditional check failed', + Item: { + id: { S: 'test-key' }, + status: { S: 'INPROGRESS' }, + expiration: { N: Date.now().toString() }, + }, }) ); // Act & Assess await expect(persistenceLayer._putRecord(record)).rejects.toThrowError( - IdempotencyItemAlreadyExistsError + new IdempotencyItemAlreadyExistsError( + `Failed to put record for already existing idempotency key: ${record.idempotencyKey}`, + new IdempotencyRecord({ + idempotencyKey: record.idempotencyKey, + status: IdempotencyRecordStatus.EXPIRED, + expiryTimestamp: Date.now() / 1000 - 1, + }) + ) ); }); @@ -676,4 +687,26 @@ describe('Class: DynamoDBPersistenceLayer', () => { }); }); }); + + test('_putRecord throws Error when Item is undefined', async () => { + // Prepare + const persistenceLayer = new TestDynamoDBPersistenceLayer({ + tableName: dummyTableName, + }); + const mockRecord = new IdempotencyRecord({ + idempotencyKey: 'test-key', + status: 'INPROGRESS', + expiryTimestamp: Date.now(), + }); + + DynamoDBClient.prototype.send = jest.fn().mockRejectedValueOnce( + new ConditionalCheckFailedException({ + message: 'Conditional check failed', + $metadata: {}, + }) + ); + await expect( + persistenceLayer._putRecord(mockRecord) + ).rejects.toThrowError(); + }); }); diff --git a/packages/logger/CHANGELOG.md b/packages/logger/CHANGELOG.md index 0f999be741..d92ed83dc3 100644 --- a/packages/logger/CHANGELOG.md +++ b/packages/logger/CHANGELOG.md @@ -3,6 +3,68 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2.0.2 (2024-03-05) + +**Note:** Version bump only for package @aws-lambda-powertools/logger + + + + + + +## 2.0.1 (2024-03-04) + +**Note:** Version bump only for package @aws-lambda-powertools/logger + + + + + +# [2.0.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.18.1...v2.0.0) (2024-03-04) + +**Note:** Version bump only for package @aws-lambda-powertools/logger + + + + + +## 1.18.1 (2024-02-20) + +**Note:** Version bump only for package @aws-lambda-powertools/logger + + + + + +## [1.18.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.17.0...v1.18.0) (2024-01-26) + +**Note:** Version bump only for package @aws-lambda-powertools/logger + +## [1.17.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.16.0...v1.17.0) (2023-11-24) + +**maintenance:** drop support for Node.js 14 ([#1664](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1664)) ([e2a0923](https://github.com/aws-powertools/powertools-lambda-typescript/commit/e2a09232f86167b5208be2daf892aa1ea433ce0f)) + +# [1.16.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.15.0...v1.16.0) (2023-11-16) + +### Features + +- **logger:** add support for `AWS_LAMBDA_LOG_LEVEL` and `POWERTOOLS_LOG_LEVEL` ([#1795](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1795)) ([e69abfb](https://github.com/aws-powertools/powertools-lambda-typescript/commit/e69abfb5f1b5d3bf993ac2fe66fae85a85af9905)) + +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) +- **metrics:** log directly to stdout ([#1786](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1786)) ([75dc5b1](https://github.com/aws-powertools/powertools-lambda-typescript/commit/75dc5b1e16944416a287628c50ec4a0cf82c3023)) + +## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) + +**Note:** Version bump only for package @aws-lambda-powertools/logger + +## [1.14.1](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.0...v1.14.1) (2023-10-31) + +**Note:** Version bump only for package @aws-lambda-powertools/logger + # [1.14.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.13.1...v1.14.0) (2023-09-29) ### Features diff --git a/packages/logger/README.md b/packages/logger/README.md index 0f5c24ce71..e457d14357 100644 --- a/packages/logger/README.md +++ b/packages/logger/README.md @@ -14,7 +14,7 @@ You can use the library in both TypeScript and JavaScript code bases. - [Getting started](#getting-started) - [Installation](#installation) - [Examples](#examples) - - [Serverless TypeScript Demo application](#serverless-typescript-demo-application) + - [Demo applications](#demo-applications) - [Contribute](#contribute) - [Roadmap](#roadmap) - [Connect](#connect) @@ -63,11 +63,13 @@ Or refer to the installation guide of each utility: * [CDK](https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/examples/cdk) * [SAM](https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/examples/sam) -### Serverless TypeScript Demo application +### Demo applications The [Serverless TypeScript Demo](https://github.com/aws-samples/serverless-typescript-demo) shows how to use Powertools for AWS Lambda (TypeScript). You can find instructions on how to deploy and load test this application in the [repository](https://github.com/aws-samples/serverless-typescript-demo). +The [AWS Lambda performance tuning](https://github.com/aws-samples/optimizations-for-lambda-functions) repository also uses Powertools for AWS Lambda (TypeScript) as well as demonstrating other performance tuning techniques for Lambda functions written in TypeScript. + ## Contribute If you are interested in contributing to this project, please refer to our [Contributing Guidelines](https://github.com/aws-powertools/powertools-lambda-typescript/blob/main/CONTRIBUTING.md). @@ -99,6 +101,8 @@ The following companies, among others, use Powertools: * [Sennder](https://sennder.com/) * [Certible](https://www.certible.com/) * [tecRacer GmbH & Co. KG](https://www.tecracer.com/) +* [AppYourself](https://appyourself.net) +* [Alma Media](https://www.almamedia.fi) ### Sharing your work diff --git a/packages/logger/package.json b/packages/logger/package.json index f38e2f388f..7da74efebb 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -1,6 +1,6 @@ { "name": "@aws-lambda-powertools/logger", - "version": "1.14.0", + "version": "2.0.2", "description": "The logging package for the Powertools for AWS Lambda (TypeScript) library", "author": { "name": "Amazon Web Services", @@ -15,6 +15,7 @@ "jest": "jest --detectOpenHandles --verbose", "test:e2e:nodejs16x": "RUNTIME=nodejs16x jest --group=e2e", "test:e2e:nodejs18x": "RUNTIME=nodejs18x jest --group=e2e", + "test:e2e:nodejs20x": "RUNTIME=nodejs20x jest --group=e2e", "test:e2e": "jest --group=e2e", "watch": "jest --watch --group=unit", "build:cjs": "tsc --build tsconfig.json && echo '{ \"type\": \"commonjs\" }' > lib/cjs/package.json", @@ -66,7 +67,7 @@ "main": "./lib/cjs/index.js", "devDependencies": { "@aws-lambda-powertools/testing-utils": "file:../testing", - "@types/lodash.merge": "^4.6.7" + "@types/lodash.merge": "^4.6.9" }, "peerDependencies": { "@middy/core": ">=3.x" @@ -87,7 +88,7 @@ "url": "https://github.com/aws-powertools/powertools-lambda-typescript/issues" }, "dependencies": { - "@aws-lambda-powertools/commons": "^1.14.0", + "@aws-lambda-powertools/commons": "^2.0.2", "lodash.merge": "^4.6.2" }, "keywords": [ diff --git a/packages/logger/src/Logger.ts b/packages/logger/src/Logger.ts index a6bed0ca2c..3a8859e447 100644 --- a/packages/logger/src/Logger.ts +++ b/packages/logger/src/Logger.ts @@ -2,6 +2,7 @@ import { Utility } from '@aws-lambda-powertools/commons'; import type { HandlerMethodDecorator } from '@aws-lambda-powertools/commons/types'; import type { Context, Handler } from 'aws-lambda'; import merge from 'lodash.merge'; +import { format } from 'node:util'; import { Console } from 'node:console'; import { randomInt } from 'node:crypto'; import { EnvironmentVariablesService } from './config/EnvironmentVariablesService.js'; @@ -57,7 +58,8 @@ import type { * * @example * ```typescript - * import { Logger, injectLambdaContext } from '@aws-lambda-powertools/logger'; + * import { Logger } from '@aws-lambda-powertools/logger'; + * import { injectLambdaContext } from '@aws-lambda-powertools/logger/middleware'; * import middy from '@middy/core'; * * const logger = new Logger(); @@ -76,7 +78,7 @@ import type { * @example * ```typescript * import { Logger } from '@aws-lambda-powertools/logger'; - * import { LambdaInterface } from '@aws-lambda-powertools/commons'; + * import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; * * const logger = new Logger(); * @@ -345,7 +347,7 @@ class Logger extends Utility implements LoggerInterface { * @example * ```typescript * import { Logger } from '@aws-lambda-powertools/logger'; - * import { LambdaInterface } from '@aws-lambda-powertools/commons'; + * import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; * * const logger = new Logger(); * @@ -430,8 +432,8 @@ class Logger extends Utility implements LoggerInterface { logger.addContext(context); let shouldLogEvent = undefined; - if (Object.hasOwn(options || {}, 'logEvent')) { - shouldLogEvent = options!.logEvent; + if (options && options.hasOwnProperty('logEvent')) { + shouldLogEvent = options.logEvent; } logger.logEventIfEnabled(event, shouldLogEvent); } @@ -477,7 +479,7 @@ class Logger extends Utility implements LoggerInterface { */ public removePersistentLogAttributes(keys: string[]): void { for (const key of keys) { - if (Object.hasOwn(this.persistentLogAttributes, key)) { + if (this.persistentLogAttributes && key in this.persistentLogAttributes) { delete this.persistentLogAttributes[key]; } } @@ -486,9 +488,13 @@ class Logger extends Utility implements LoggerInterface { /** * Set the log level for this Logger instance. * + * If the log level is set using AWS Lambda Advanced Logging Controls, it sets it + * instead of the given log level to avoid data loss. + * * @param logLevel The log level to set, i.e. `error`, `warn`, `info`, `debug`, etc. */ public setLogLevel(logLevel: LogLevel): void { + if (this.awsLogLevelShortCircuit(logLevel)) return; if (this.isValidLogLevel(logLevel)) { this.logLevel = this.logLevelThresholds[logLevel]; } else { @@ -570,6 +576,30 @@ class Logger extends Utility implements LoggerInterface { merge(this.powertoolsLogData, attributes); } + private awsLogLevelShortCircuit(selectedLogLevel?: string): boolean { + const awsLogLevel = this.getEnvVarsService().getAwsLogLevel(); + if (this.isValidLogLevel(awsLogLevel)) { + this.logLevel = this.logLevelThresholds[awsLogLevel]; + + if ( + this.isValidLogLevel(selectedLogLevel) && + this.logLevel > this.logLevelThresholds[selectedLogLevel] + ) { + this.warn( + format( + `Current log level (%s) does not match AWS Lambda Advanced Logging Controls minimum log level (%s). This can lead to data loss, consider adjusting them.`, + selectedLogLevel, + awsLogLevel + ) + ); + } + + return true; + } + + return false; + } + /** * It processes a particular log item so that it can be printed to stdout: * - Merges ephemeral log attributes with persistent log attributes (printed for all logs) and additional info; @@ -610,8 +640,8 @@ class Logger extends Utility implements LoggerInterface { item instanceof Error ? { error: item } : typeof item === 'string' - ? { extra: item } - : item; + ? { extra: item } + : item; additionalLogAttributes = merge(additionalLogAttributes, attributes); }); @@ -845,17 +875,21 @@ class Logger extends Utility implements LoggerInterface { /** * Sets the initial Logger log level based on the following order: - * 1. If a log level is passed to the constructor, it sets it. - * 2. If a log level is set via custom config service, it sets it. - * 3. If a log level is set via env variables, it sets it. + * 1. If a log level is set using AWS Lambda Advanced Logging Controls, it sets it. + * 2. If a log level is passed to the constructor, it sets it. + * 3. If a log level is set via custom config service, it sets it. + * 4. If a log level is set via env variables, it sets it. * - * If none of the above is true, the default log level applies (INFO). + * If none of the above is true, the default log level applies (`INFO`). * * @private * @param {LogLevel} [logLevel] - Log level passed to the constructor */ private setInitialLogLevel(logLevel?: LogLevel): void { const constructorLogLevel = logLevel?.toUpperCase(); + + if (this.awsLogLevelShortCircuit(constructorLogLevel)) return; + if (this.isValidLogLevel(constructorLogLevel)) { this.logLevel = this.logLevelThresholds[constructorLogLevel]; diff --git a/packages/logger/src/config/EnvironmentVariablesService.ts b/packages/logger/src/config/EnvironmentVariablesService.ts index 846930a913..55188ee093 100644 --- a/packages/logger/src/config/EnvironmentVariablesService.ts +++ b/packages/logger/src/config/EnvironmentVariablesService.ts @@ -20,17 +20,35 @@ class EnvironmentVariablesService implements ConfigServiceInterface { // Reserved environment variables + private awsLogLevelVariable = 'AWS_LAMBDA_LOG_LEVEL'; private awsRegionVariable = 'AWS_REGION'; private currentEnvironmentVariable = 'ENVIRONMENT'; - private devModeVariable = 'POWERTOOLS_DEV'; private functionNameVariable = 'AWS_LAMBDA_FUNCTION_NAME'; private functionVersionVariable = 'AWS_LAMBDA_FUNCTION_VERSION'; private logEventVariable = 'POWERTOOLS_LOGGER_LOG_EVENT'; - private logLevelVariable = 'LOG_LEVEL'; + private logLevelVariable = 'POWERTOOLS_LOG_LEVEL'; + private logLevelVariableLegacy = 'LOG_LEVEL'; private memoryLimitInMBVariable = 'AWS_LAMBDA_FUNCTION_MEMORY_SIZE'; private sampleRateValueVariable = 'POWERTOOLS_LOGGER_SAMPLE_RATE'; private tzVariable = 'TZ'; + /** + * It returns the value of the `AWS_LAMBDA_LOG_LEVEL` environment variable. + * + * The `AWS_LAMBDA_LOG_LEVEL` environment variable is set by AWS Lambda when configuring + * the function's log level using the Advanced Logging Controls feature. This value always + * takes precedence over other means of configuring the log level. + * + * @note we need to map the `FATAL` log level to `CRITICAL`, see {@link https://docs.aws.amazon.com/lambda/latest/dg/configuration-logging.html#configuration-logging-log-levels AWS Lambda Log Levels}. + * + * @returns {string} + */ + public getAwsLogLevel(): string { + const awsLogLevelVariable = this.get(this.awsLogLevelVariable); + + return awsLogLevelVariable === 'FATAL' ? 'CRITICAL' : awsLogLevelVariable; + } + /** * It returns the value of the AWS_REGION environment variable. * @@ -90,12 +108,19 @@ class EnvironmentVariablesService } /** - * It returns the value of the LOG_LEVEL environment variable. + * It returns the value of the `POWERTOOLS_LOG_LEVEL, or `LOG_LEVEL` (legacy) environment variables + * when the first one is not set. + * + * @note The `LOG_LEVEL` environment variable is considered legacy and will be removed in a future release. + * @note The `AWS_LAMBDA_LOG_LEVEL` environment variable always takes precedence over the ones above. * * @returns {string} */ public getLogLevel(): string { - return this.get(this.logLevelVariable); + const logLevelVariable = this.get(this.logLevelVariable); + const logLevelVariableAlias = this.get(this.logLevelVariableLegacy); + + return logLevelVariable !== '' ? logLevelVariable : logLevelVariableAlias; } /** @@ -119,17 +144,6 @@ class EnvironmentVariablesService return value.length > 0 ? value : 'UTC'; } - - /** - * It returns true if the POWERTOOLS_DEV environment variable is set to truthy value. - * - * @returns {boolean} - */ - public isDevMode(): boolean { - const value = this.get(this.devModeVariable); - - return this.isValueTrue(value); - } } export { EnvironmentVariablesService }; diff --git a/packages/logger/src/formatter/LogFormatter.ts b/packages/logger/src/formatter/LogFormatter.ts index 3f723d67a4..dd874732c4 100644 --- a/packages/logger/src/formatter/LogFormatter.ts +++ b/packages/logger/src/formatter/LogFormatter.ts @@ -7,6 +7,22 @@ import type { import type { UnformattedAttributes } from '../types/Logger.js'; import { LogItem } from './LogItem.js'; +/** + * Typeguard to monkey patch Error to add a cause property. + * + * This is needed because the `cause` property is present in ES2022 or newer. + * Since we want to be able to format errors in Node 16.x, we need to + * add this property ourselves. We can remove this once we drop support + * for Node 16.x. + * + * @see https://nodejs.org/api/errors.html#errors_error_cause + */ +const isErrorWithCause = ( + error: Error +): error is Error & { cause: unknown } => { + return 'cause' in error; +}; + /** * This class defines and implements common methods for the formatting of log attributes. * @@ -49,10 +65,11 @@ abstract class LogFormatter implements LogFormatterInterface { location: this.getCodeLocation(error.stack), message: error.message, stack: error.stack, - cause: - error.cause instanceof Error + cause: isErrorWithCause(error) + ? error.cause instanceof Error ? this.formatError(error.cause) - : error.cause, + : error.cause + : undefined, }; } diff --git a/packages/logger/src/middleware/middy.ts b/packages/logger/src/middleware/middy.ts index d40be85cd2..4e970e55a9 100644 --- a/packages/logger/src/middleware/middy.ts +++ b/packages/logger/src/middleware/middy.ts @@ -14,7 +14,8 @@ import type { * * @example * ```typescript - * import { Logger, injectLambdaContext } from '@aws-lambda-powertools/logger'; + * import { Logger } from '@aws-lambda-powertools/logger'; + * import { injectLambdaContext } from '@aws-lambda-powertools/logger/middleware'; * import middy from '@middy/core'; * * diff --git a/packages/logger/src/types/ConfigServiceInterface.ts b/packages/logger/src/types/ConfigServiceInterface.ts index ccaf34cf80..eea0b0200a 100644 --- a/packages/logger/src/types/ConfigServiceInterface.ts +++ b/packages/logger/src/types/ConfigServiceInterface.ts @@ -1,3 +1,5 @@ +import type { ConfigServiceInterface as ConfigServiceBaseInterface } from '@aws-lambda-powertools/commons/types'; + /** * Interface ConfigServiceInterface * @@ -5,14 +7,19 @@ * @see https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime * @see https://docs.powertools.aws.dev/lambda/typescript/latest/#environment-variables */ -interface ConfigServiceInterface { +interface ConfigServiceInterface extends ConfigServiceBaseInterface { /** - * It returns the value of an environment variable that has given name. + * It returns the value of the `AWS_LAMBDA_LOG_LEVEL` environment variable. + * + * The `AWS_LAMBDA_LOG_LEVEL` environment variable is set by AWS Lambda when configuring + * the function's log level using the Advanced Logging Controls feature. This value always + * takes precedence over other means of configuring the log level. + * + * @note we need to map the `FATAL` log level to `CRITICAL`, see {@link https://docs.aws.amazon.com/lambda/latest/dg/configuration-logging.html#configuration-logging-log-levels AWS Lambda Log Levels}. * - * @param {string} name * @returns {string} */ - get(name: string): string; + getAwsLogLevel(): string; /** * It returns the value of the ENVIRONMENT environment variable. @@ -29,7 +36,11 @@ interface ConfigServiceInterface { getLogEvent(): boolean; /** - * It returns the value of the LOG_LEVEL environment variable. + * It returns the value of the `POWERTOOLS_LOG_LEVEL, or `LOG_LEVEL` (legacy) environment variables + * when the first one is not set. + * + * @note The `LOG_LEVEL` environment variable is considered legacy and will be removed in a future release. + * @note The `AWS_LAMBDA_LOG_LEVEL` environment variable always takes precedence over the ones above. * * @returns {string} */ @@ -41,28 +52,6 @@ interface ConfigServiceInterface { * @returns {string|undefined} */ getSampleRateValue(): number | undefined; - - /** - * It returns the value of the POWERTOOLS_SERVICE_NAME environment variable. - * - * @returns {string} - */ - getServiceName(): string; - - /** - * It returns the value of the POWERTOOLS_DEV environment variable. - * - * @returns {boolean} - */ - isDevMode(): boolean; - - /** - * It returns true if the string value represents a boolean true value. - * - * @param {string} value - * @returns boolean - */ - isValueTrue(value: string): boolean; } export type { ConfigServiceInterface }; diff --git a/packages/logger/tests/e2e/basicFeatures.middy.test.ts b/packages/logger/tests/e2e/basicFeatures.middy.test.ts index 6ec5719206..5f7a67eb35 100644 --- a/packages/logger/tests/e2e/basicFeatures.middy.test.ts +++ b/packages/logger/tests/e2e/basicFeatures.middy.test.ts @@ -72,7 +72,7 @@ describe(`Logger E2E tests, basic functionalities middy usage`, () => { describe('Log level filtering', () => { it( - 'should filter log based on LOG_LEVEL (INFO) environment variable in Lambda', + 'should filter log based on POWERTOOLS_LOG_LEVEL (INFO) environment variable in Lambda', async () => { for (let i = 0; i < invocationCount; i++) { // Get log messages of the invocation and filter by level diff --git a/packages/logger/tests/e2e/constants.ts b/packages/logger/tests/e2e/constants.ts index d4e2b18e8e..a719a35b83 100644 --- a/packages/logger/tests/e2e/constants.ts +++ b/packages/logger/tests/e2e/constants.ts @@ -3,7 +3,7 @@ import { randomUUID } from 'node:crypto'; const RESOURCE_NAME_PREFIX = 'Logger'; const ONE_MINUTE = 60 * 1000; const TEST_CASE_TIMEOUT = ONE_MINUTE; -const SETUP_TIMEOUT = 5 * ONE_MINUTE; +const SETUP_TIMEOUT = 7 * ONE_MINUTE; const TEARDOWN_TIMEOUT = 5 * ONE_MINUTE; const STACK_OUTPUT_LOG_GROUP = 'LogGroupName'; const XRAY_TRACE_ID_REGEX = /^1-[0-9a-f]{8}-[0-9a-f]{24}$/; @@ -23,7 +23,7 @@ const commonEnvironmentVars = { CHILD_LOG_MSG: 'child-only-log-msg', CHILD_LOG_LEVEL: 'ERROR', POWERTOOLS_SERVICE_NAME: 'logger-e2e-testing', - LOG_LEVEL: 'INFO', + POWERTOOLS_LOG_LEVEL: 'INFO', }; export { diff --git a/packages/logger/tests/e2e/sampleRate.decorator.test.ts b/packages/logger/tests/e2e/sampleRate.decorator.test.ts index cf22722e7f..d6db70c8c0 100644 --- a/packages/logger/tests/e2e/sampleRate.decorator.test.ts +++ b/packages/logger/tests/e2e/sampleRate.decorator.test.ts @@ -44,7 +44,7 @@ describe(`Logger E2E tests, sample rate and injectLambdaContext()`, () => { { entry: lambdaFunctionCodeFilePath, environment: { - LOG_LEVEL: 'ERROR', + POWERTOOLS_LOG_LEVEL: 'ERROR', SAMPLE_RATE: '0.5', LOG_MSG: `Log message ${randomUUID()}`, }, diff --git a/packages/logger/tests/helpers/populateEnvironmentVariables.ts b/packages/logger/tests/helpers/populateEnvironmentVariables.ts index b993a774ba..9c7e47f8cf 100644 --- a/packages/logger/tests/helpers/populateEnvironmentVariables.ts +++ b/packages/logger/tests/helpers/populateEnvironmentVariables.ts @@ -11,5 +11,5 @@ if ( } // Powertools for AWS Lambda (TypeScript) variables -process.env.LOG_LEVEL = 'DEBUG'; +process.env.POWERTOOLS_LOG_LEVEL = 'DEBUG'; process.env.POWERTOOLS_SERVICE_NAME = 'hello-world'; diff --git a/packages/logger/tests/unit/EnvironmentVariablesService.test.ts b/packages/logger/tests/unit/EnvironmentVariablesService.test.ts index cb5850b3d7..1d40af9e9f 100644 --- a/packages/logger/tests/unit/EnvironmentVariablesService.test.ts +++ b/packages/logger/tests/unit/EnvironmentVariablesService.test.ts @@ -17,6 +17,20 @@ describe('Class: EnvironmentVariablesService', () => { process.env = ENVIRONMENT_VARIABLES; }); + describe('Method: getAwsLogLevel', () => { + it('returns the value of the environment variable AWS_LAMBDA_LOG_LEVEL and aliases it as needed', () => { + // Prepare + process.env.AWS_LAMBDA_LOG_LEVEL = 'FATAL'; + const service = new EnvironmentVariablesService(); + + // Act + const value = service.getAwsLogLevel(); + + // Assess + expect(value).toEqual('CRITICAL'); + }); + }); + describe('Method: getAwsRegion', () => { test('it returns the value of the environment variable AWS_REGION', () => { // Prepare @@ -126,8 +140,9 @@ describe('Class: EnvironmentVariablesService', () => { }); describe('Method: getLogLevel', () => { - test('it returns the value of the environment variable LOG_LEVEL', () => { + test('it returns the value of the environment variable LOG_LEVEL when POWERTOOLS_LOG_LEVEL is not set', () => { // Prepare + process.env.POWERTOOLS_LOG_LEVEL = undefined; process.env.LOG_LEVEL = 'ERROR'; const service = new EnvironmentVariablesService(); @@ -137,94 +152,70 @@ describe('Class: EnvironmentVariablesService', () => { // Assess expect(value).toEqual('ERROR'); }); - }); - - describe('Method: getSampleRateValue', () => { - test('it returns the value of the environment variable POWERTOOLS_LOGGER_SAMPLE_RATE', () => { - // Prepare - process.env.POWERTOOLS_LOGGER_SAMPLE_RATE = '0.01'; - const service = new EnvironmentVariablesService(); - - // Act - const value = service.getSampleRateValue(); - - // Assess - expect(value).toEqual(0.01); - }); - }); - describe('Method: getTimezone', () => { - it('returns the value of the TZ environment variable when set', () => { + test('it returns the value of the environment variable POWERTOOLS_LOG_LEVEL when LOG_LEVEL one is also set', () => { // Prepare - process.env.TZ = 'Europe/London'; + process.env.LOG_LEVEL = 'WARN'; + process.env.POWERTOOLS_LOG_LEVEL = 'INFO'; const service = new EnvironmentVariablesService(); // Act - const value = service.getTimezone(); + const value = service.getLogLevel(); // Assess - expect(value).toEqual('Europe/London'); + expect(value).toEqual('INFO'); }); - it('returns the default UTC value when no TZ is set', () => { + test('it returns an empty value if neither POWERTOOLS_LOG_LEVEL nor LOG_LEVEL are set', () => { // Prepare + process.env.LOG_LEVEL = undefined; + process.env.POWERTOOLS_LOG_LEVEL = undefined; const service = new EnvironmentVariablesService(); // Act - const value = service.getTimezone(); + const value = service.getLogLevel(); // Assess - expect(value).toEqual('UTC'); + expect(value).toEqual(''); }); }); - describe('Method: isDevMode', () => { - test('it returns true if the environment variable POWERTOOLS_DEV is "true"', () => { - // Prepare - process.env.POWERTOOLS_DEV = 'true'; - const service = new EnvironmentVariablesService(); - - // Act - const value = service.isDevMode(); - - // Assess - expect(value).toEqual(true); - }); - - test('it returns false if the environment variable POWERTOOLS_DEV is "false"', () => { + describe('Method: getSampleRateValue', () => { + test('it returns the value of the environment variable POWERTOOLS_LOGGER_SAMPLE_RATE', () => { // Prepare - process.env.POWERTOOLS_DEV = 'false'; + process.env.POWERTOOLS_LOGGER_SAMPLE_RATE = '0.01'; const service = new EnvironmentVariablesService(); // Act - const value = service.isDevMode(); + const value = service.getSampleRateValue(); // Assess - expect(value).toEqual(false); + expect(value).toEqual(0.01); }); + }); - test('it returns false if the environment variable POWERTOOLS_DEV is NOT set', () => { + describe('Method: getTimezone', () => { + it('returns the value of the TZ environment variable when set', () => { // Prepare - process.env.POWERTOOLS_DEV = 'somethingsilly'; + process.env.TZ = 'Europe/London'; const service = new EnvironmentVariablesService(); // Act - const value = service.isDevMode(); + const value = service.getTimezone(); // Assess - expect(value).toEqual(false); + expect(value).toEqual('Europe/London'); }); - test('it returns false if the environment variable POWERTOOLS_DEV is "somethingsilly"', () => { + it('returns the default UTC value when no TZ is set', () => { // Prepare - process.env.POWERTOOLS_DEV = 'somethingsilly'; const service = new EnvironmentVariablesService(); // Act - const value = service.isDevMode(); + const value = service.getTimezone(); // Assess - expect(value).toEqual(false); + expect(value).toEqual('UTC'); }); }); }); diff --git a/packages/logger/tests/unit/Logger.test.ts b/packages/logger/tests/unit/Logger.test.ts index 8cc185aeb7..b5f8ae462a 100644 --- a/packages/logger/tests/unit/Logger.test.ts +++ b/packages/logger/tests/unit/Logger.test.ts @@ -136,7 +136,7 @@ describe('Class: Logger', () => { // Prepare const loggerOptions = undefined; delete process.env.POWERTOOLS_SERVICE_NAME; - delete process.env.LOG_LEVEL; + delete process.env.POWERTOOLS_LOG_LEVEL; // Act const logger = new Logger(loggerOptions); @@ -286,7 +286,7 @@ describe('Class: Logger', () => { test('when no log level is set, returns a Logger instance with INFO level', () => { // Prepare const loggerOptions: ConstructorOptions = {}; - delete process.env.LOG_LEVEL; + delete process.env.POWERTOOLS_LOG_LEVEL; // Act const logger = new Logger(loggerOptions); @@ -354,6 +354,9 @@ describe('Class: Logger', () => { get(name: string): string { return `a-string-from-${name}`; }, + getAwsLogLevel() { + return 'INFO'; + }, getCurrentEnvironment(): string { return 'dev'; }, @@ -369,6 +372,9 @@ describe('Class: Logger', () => { getServiceName(): string { return 'my-backend-service'; }, + getXrayTraceId(): string | undefined { + return undefined; + }, isDevMode(): boolean { return false; }, @@ -638,9 +644,9 @@ describe('Class: Logger', () => { expect(consoleSpy).toBeCalledTimes(0); }); - test('when the log level is set through LOG_LEVEL env variable, it DOES print to stdout', () => { + test('when the log level is set through POWERTOOLS_LOG_LEVEL env variable, it DOES print to stdout', () => { // Prepare - process.env.LOG_LEVEL = methodOfLogger.toUpperCase(); + process.env.POWERTOOLS_LOG_LEVEL = methodOfLogger.toUpperCase(); const logger = new Logger(); const consoleSpy = jest.spyOn( logger['console'], @@ -2528,6 +2534,26 @@ describe('Class: Logger', () => { 'Invalid log level: INVALID' ); }); + + it('uses log level set by ALC & emits a warning when setting a higher log level than ALC', () => { + // Prepare + process.env.AWS_LAMBDA_LOG_LEVEL = 'ERROR'; + process.env.LOG_LEVEL = undefined; + process.env.POWERTOOLS_LOG_LEVEL = undefined; + const logger = new Logger(); + const warningSpy = jest.spyOn(logger, 'warn'); + + // Act + logger.setLogLevel('WARN'); + + // Assess + expect(logger.level).toBe(20); + expect(logger.getLevelName()).toBe('ERROR'); + expect(warningSpy).toHaveBeenCalledTimes(1); + expect(warningSpy).toHaveBeenCalledWith( + 'Current log level (WARN) does not match AWS Lambda Advanced Logging Controls minimum log level (ERROR). This can lead to data loss, consider adjusting them.' + ); + }); }); describe('Feature: Sampling debug logs', () => { diff --git a/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts b/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts index 3a97c9637b..d3c1f289cb 100644 --- a/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts +++ b/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts @@ -3,7 +3,7 @@ * * @group unit/logger/logFormatter */ -import { AssertionError, strictEqual } from 'node:assert'; +import { AssertionError } from 'node:assert'; import { PowertoolsLogFormatter } from '../../../src/formatter/PowertoolsLogFormatter.js'; import { LogItem } from '../../../src/index.js'; import type { UnformattedAttributes } from '../../../src/types/Logger.js'; @@ -108,205 +108,134 @@ describe('Class: PowertoolsLogFormatter', () => { test('when an error of type Error is passed, it returns an object with expected structure and values', () => { // Prepare const formatter = new PowertoolsLogFormatter(); - const shouldThrow = (): void => { - throw new Error('Ouch!'); - }; - - // Act - try { - shouldThrow(); - } catch (error) { - // Assess - expect(error).toBeInstanceOf(Error); - const formattedError = formatter.formatError(error); - expect(formattedError).toEqual({ - location: expect.stringMatching( - /PowertoolsLogFormatter.test.ts:\d+$/ - ), - message: 'Ouch!', - name: 'Error', - stack: expect.stringMatching( - /PowertoolsLogFormatter.test.ts:\d+:\d+/ - ), - }); - } - expect(shouldThrow).toThrowError(expect.any(Error)); + // Act & Assess + const formattedError = formatter.formatError(new Error('Ouch!')); + expect(formattedError).toEqual({ + location: expect.stringMatching(/PowertoolsLogFormatter.test.ts:\d+$/), + message: 'Ouch!', + name: 'Error', + stack: expect.stringMatching(/PowertoolsLogFormatter.test.ts:\d+:\d+/), + }); }); test('when an error of type ReferenceError is passed, it returns an object with expected structure and values', () => { // Prepare const formatter = new PowertoolsLogFormatter(); - const shouldThrow = (): void => { - // This is a reference error purposely to test the formatter - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - doesNotExist; - }; - - // Act - try { - shouldThrow(); - } catch (error) { - // Assess - expect(error).toBeInstanceOf(Error); - const formattedReferenceError = formatter.formatError(error); - expect(formattedReferenceError).toEqual({ - location: expect.stringMatching( - /PowertoolsLogFormatter.test.ts:\d+$/ - ), - message: 'doesNotExist is not defined', - name: 'ReferenceError', - stack: expect.stringMatching( - /PowertoolsLogFormatter.test.ts:\d+:\d+/ - ), - }); - } - expect(shouldThrow).toThrowError(expect.any(ReferenceError)); + // Act & Assess + const formattedReferenceError = formatter.formatError( + new ReferenceError('doesNotExist is not defined') + ); + expect(formattedReferenceError).toEqual({ + location: expect.stringMatching(/PowertoolsLogFormatter.test.ts:\d+$/), + message: 'doesNotExist is not defined', + name: 'ReferenceError', + stack: expect.stringMatching(/PowertoolsLogFormatter.test.ts:\d+:\d+/), + }); }); test('when an error of type AssertionError is passed, it returns an object with expected structure and values', () => { // Prepare const formatter = new PowertoolsLogFormatter(); - const shouldThrow = (): void => { - strictEqual(1, 2); - }; - // Act - try { - shouldThrow(); - } catch (error) { - // Assess - expect(error).toBeInstanceOf(AssertionError); - const formattedAssertionError = formatter.formatError( - error - ); - expect(formattedAssertionError).toEqual({ - location: expect.stringMatching(/PowertoolsLogFormatter.test.ts:\d+/), - message: expect.stringMatching( - /Expected values to be strictly equal/ - ), - name: 'AssertionError', - stack: expect.stringMatching( - /PowertoolsLogFormatter.test.ts:\d+:\d+/ - ), - }); - } - - expect(shouldThrow).toThrowError(expect.any(AssertionError)); + // Act & Assess + const formattedAssertionError = formatter.formatError( + new AssertionError({ + message: 'Expected values to be strictly equal', + actual: 1, + expected: 2, + operator: 'strictEqual', + }) + ); + expect(formattedAssertionError).toEqual({ + location: expect.stringMatching( + /(node:)*internal\/assert\/assertion_error(.js)*:\d+$/ + ), + message: expect.stringMatching(/Expected values to be strictly equal/), + name: 'AssertionError', + stack: expect.stringMatching(/PowertoolsLogFormatter.test.ts:\d+:\d+/), + }); }); test('when an error of type RangeError is passed, it returns an object with expected structure and values', () => { // Prepare const formatter = new PowertoolsLogFormatter(); - const shouldThrow = (): void => { - throw new RangeError('The argument must be between 10 and 20'); - }; - // Act - try { - shouldThrow(); - } catch (error) { - // Assess - expect(error).toBeInstanceOf(RangeError); - const formattedRangeError = formatter.formatError(error); - expect(formattedRangeError).toEqual({ - location: expect.stringMatching(/PowertoolsLogFormatter.test.ts:\d+/), - message: 'The argument must be between 10 and 20', - name: 'RangeError', - stack: expect.stringMatching( - /PowertoolsLogFormatter.test.ts:\d+:\d+/ - ), - }); - } + // Act & Assess + const formattedRangeError = formatter.formatError( + new RangeError('The argument must be between 10 and 20') + ); + expect(formattedRangeError).toEqual({ + location: expect.stringMatching(/PowertoolsLogFormatter.test.ts:\d+/), + message: 'The argument must be between 10 and 20', + name: 'RangeError', + stack: expect.stringMatching(/PowertoolsLogFormatter.test.ts:\d+:\d+/), + }); + }); - expect(shouldThrow).toThrowError(expect.any(RangeError)); + test('when an error of type ReferenceError is passed, it returns an object with expected structure and values', () => { + // Prepare + const formatter = new PowertoolsLogFormatter(); + + // Act & Assess + const formattedError = formatter.formatError( + new ReferenceError('foo is not defined') + ); + expect(formattedError).toEqual({ + location: expect.stringMatching(/PowertoolsLogFormatter.test.ts:\d+/), + message: 'foo is not defined', + name: 'ReferenceError', + stack: expect.stringMatching(/PowertoolsLogFormatter.test.ts:\d+:\d+/), + }); }); test('when an error of type SyntaxError is passed, it returns an object with expected structure and values', () => { // Prepare const formatter = new PowertoolsLogFormatter(); - const shouldThrow = (): void => { - eval('foo bar'); - }; - // Act - try { - shouldThrow(); - } catch (error) { - // Assess - expect(error).toBeInstanceOf(SyntaxError); - const formattedSyntaxError = formatter.formatError(error); - expect(formattedSyntaxError).toEqual({ - location: expect.stringMatching(/PowertoolsLogFormatter.test.ts:\d+/), - message: 'Unexpected identifier', - name: 'SyntaxError', - stack: expect.stringMatching( - /PowertoolsLogFormatter.test.ts:\d+:\d+/ - ), - }); - } - - expect(shouldThrow).toThrowError(expect.any(SyntaxError)); + // Act & Assess + const formattedSyntaxError = formatter.formatError( + new SyntaxError(`Unexpected identifier 'bar'`) + ); + expect(formattedSyntaxError).toEqual({ + location: expect.stringMatching(/PowertoolsLogFormatter.test.ts:\d+/), + message: `Unexpected identifier 'bar'`, + name: 'SyntaxError', + stack: expect.stringMatching(/PowertoolsLogFormatter.test.ts:\d+:\d+/), + }); }); test('when an error of type TypeError is passed, it returns an object with expected structure and values', () => { // Prepare const formatter = new PowertoolsLogFormatter(); - const shouldThrow = (): void => { - // This is a reference error purposely to test the formatter - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - null.foo(); - }; - - // Act - try { - shouldThrow(); - } catch (error) { - // TODO: review message content assertion (see Issue #304) - // Assess - expect(error).toBeInstanceOf(Error); - const formattedTypeError = formatter.formatError(error); - expect(formattedTypeError).toEqual({ - location: expect.stringMatching(/PowertoolsLogFormatter.test.ts:\d+/), - message: expect.stringMatching(/Cannot read propert/), - name: 'TypeError', - stack: expect.stringMatching( - /PowertoolsLogFormatter.test.ts:\d+:\d+/ - ), - }); - } - expect(shouldThrow).toThrowError(expect.any(TypeError)); + // Act & Assess + const formattedTypeError = formatter.formatError( + new TypeError(`Cannot read property 'foo' of null`) + ); + expect(formattedTypeError).toEqual({ + location: expect.stringMatching(/PowertoolsLogFormatter.test.ts:\d+/), + message: expect.stringMatching(/Cannot read propert/), + name: 'TypeError', + stack: expect.stringMatching(/PowertoolsLogFormatter.test.ts:\d+:\d+/), + }); }); test('when an error of type URIError is passed, it returns an object with expected structure and values', () => { // Prepare const formatter = new PowertoolsLogFormatter(); - const shouldThrow = (): void => { - decodeURIComponent('%'); - }; - // Act - try { - shouldThrow(); - } catch (error) { - // Assess - expect(error).toBeInstanceOf(URIError); - const formattedURIError = formatter.formatError(error); - expect(formattedURIError).toEqual({ - location: expect.stringMatching(/PowertoolsLogFormatter.test.ts:\d+/), - message: 'URI malformed', - name: 'URIError', - stack: expect.stringMatching( - /PowertoolsLogFormatter.test.ts:\d+:\d+/ - ), - }); - } - - expect(shouldThrow).toThrowError(expect.any(URIError)); + // Act & Assess + const formattedURIError = formatter.formatError( + new URIError('URI malformed') + ); + expect(formattedURIError).toEqual({ + location: expect.stringMatching(/PowertoolsLogFormatter.test.ts:\d+/), + message: 'URI malformed', + name: 'URIError', + stack: expect.stringMatching(/PowertoolsLogFormatter.test.ts:\d+:\d+/), + }); }); test('when an error with cause of type Error is formatted, the cause key is included and formatted', () => { diff --git a/packages/logger/tests/unit/middleware/middy.test.ts b/packages/logger/tests/unit/middleware/middy.test.ts index 02738d3a33..532b923c03 100644 --- a/packages/logger/tests/unit/middleware/middy.test.ts +++ b/packages/logger/tests/unit/middleware/middy.test.ts @@ -274,6 +274,9 @@ describe('Middy middleware', () => { get(name: string): string { return `a-string-from-${name}`; }, + getAwsLogLevel(): string { + return 'INFO'; + }, getCurrentEnvironment(): string { return 'dev'; }, @@ -289,6 +292,9 @@ describe('Middy middleware', () => { getServiceName(): string { return 'my-backend-service'; }, + getXrayTraceId(): string | undefined { + return undefined; + }, isDevMode(): boolean { return false; }, diff --git a/packages/metrics/CHANGELOG.md b/packages/metrics/CHANGELOG.md index 97ce109888..a6302ae611 100644 --- a/packages/metrics/CHANGELOG.md +++ b/packages/metrics/CHANGELOG.md @@ -3,6 +3,68 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2.0.2 (2024-03-05) + +**Note:** Version bump only for package @aws-lambda-powertools/metrics + + + + + + +## 2.0.1 (2024-03-04) + +**Note:** Version bump only for package @aws-lambda-powertools/metrics + + + + + +# [2.0.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.18.1...v2.0.0) (2024-03-04) + +**Note:** Version bump only for package @aws-lambda-powertools/metrics + + + + + +## 1.18.1 (2024-02-20) + +**Note:** Version bump only for package @aws-lambda-powertools/metrics + + + + + +## [1.18.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.17.0...v1.18.0) (2024-01-26) + +**Note:** Version bump only for package @aws-lambda-powertools/metrics + +## [1.17.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.16.0...v1.17.0) (2023-11-24) + +**maintenance:** drop support for Node.js 14 ([#1664](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1664)) ([e2a0923](https://github.com/aws-powertools/powertools-lambda-typescript/commit/e2a09232f86167b5208be2daf892aa1ea433ce0f)) + +# [1.16.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.15.0...v1.16.0) (2023-11-16) + +**Note:** Version bump only for package @aws-lambda-powertools/metrics + +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) +- **metrics:** log directly to stdout ([#1786](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1786)) ([75dc5b1](https://github.com/aws-powertools/powertools-lambda-typescript/commit/75dc5b1e16944416a287628c50ec4a0cf82c3023)) + +## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) + +### Bug Fixes + +- **metrics:** deduplicate dimensions when serialising ([#1780](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1780)) ([8181b48](https://github.com/aws-powertools/powertools-lambda-typescript/commit/8181b481ba96fa7a91959ff2d40bdedfe80b451b)) + +## [1.14.1](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.0...v1.14.1) (2023-10-31) + +**Note:** Version bump only for package @aws-lambda-powertools/metrics + # [1.14.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.13.1...v1.14.0) (2023-09-29) ### Features diff --git a/packages/metrics/README.md b/packages/metrics/README.md index 088675b0e3..dcd1d01588 100644 --- a/packages/metrics/README.md +++ b/packages/metrics/README.md @@ -14,7 +14,7 @@ You can use the library in both TypeScript and JavaScript code bases. - [Getting started](#getting-started) - [Installation](#installation) - [Examples](#examples) - - [Serverless TypeScript Demo application](#serverless-typescript-demo-application) + - [Demo applications](#demo-applications) - [Contribute](#contribute) - [Roadmap](#roadmap) - [Connect](#connect) @@ -62,11 +62,13 @@ Or refer to the installation guide of each utility: * [CDK](https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/examples/cdk) * [SAM](https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/examples/sam) -### Serverless TypeScript Demo application +### Demo applications The [Serverless TypeScript Demo](https://github.com/aws-samples/serverless-typescript-demo) shows how to use Powertools for AWS Lambda (TypeScript). You can find instructions on how to deploy and load test this application in the [repository](https://github.com/aws-samples/serverless-typescript-demo). +The [AWS Lambda performance tuning](https://github.com/aws-samples/optimizations-for-lambda-functions) repository also uses Powertools for AWS Lambda (TypeScript) as well as demonstrating other performance tuning techniques for Lambda functions written in TypeScript. + ## Contribute If you are interested in contributing to this project, please refer to our [Contributing Guidelines](https://github.com/aws-powertools/powertools-lambda-typescript/blob/main/CONTRIBUTING.md). @@ -98,6 +100,8 @@ The following companies, among others, use Powertools: * [Sennder](https://sennder.com/) * [Certible](https://www.certible.com/) * [tecRacer GmbH & Co. KG](https://www.tecracer.com/) +* [AppYourself](https://appyourself.net) +* [Alma Media](https://www.almamedia.fi) ### Sharing your work diff --git a/packages/metrics/package.json b/packages/metrics/package.json index ad3a9171d5..477dd9c2cb 100644 --- a/packages/metrics/package.json +++ b/packages/metrics/package.json @@ -1,6 +1,6 @@ { "name": "@aws-lambda-powertools/metrics", - "version": "1.14.0", + "version": "2.0.2", "description": "The metrics package for the Powertools for AWS Lambda (TypeScript) library", "author": { "name": "Amazon Web Services", @@ -12,9 +12,9 @@ "scripts": { "test": "npm run test:unit", "test:unit": "jest --group=unit --detectOpenHandles --coverage --verbose", - "jest": "jest --detectOpenHandles --verbose", "test:e2e:nodejs16x": "RUNTIME=nodejs16x jest --group=e2e", "test:e2e:nodejs18x": "RUNTIME=nodejs18x jest --group=e2e", + "test:e2e:nodejs20x": "RUNTIME=nodejs20x jest --group=e2e", "test:e2e": "jest --group=e2e", "watch": "jest --group=unit --watch ", "build:cjs": "tsc --build tsconfig.json && echo '{ \"type\": \"commonjs\" }' > lib/cjs/package.json", @@ -66,7 +66,7 @@ "main": "./lib/cjs/index.js", "devDependencies": { "@aws-lambda-powertools/testing-utils": "file:../testing", - "@aws-sdk/client-cloudwatch": "^3.438.0", + "@aws-sdk/client-cloudwatch": "^3.525.0", "@types/promise-retry": "^1.1.3", "promise-retry": "^2.0.1" }, @@ -89,7 +89,7 @@ "url": "https://github.com/aws-powertools/powertools-lambda-typescript/issues" }, "dependencies": { - "@aws-lambda-powertools/commons": "^1.14.0" + "@aws-lambda-powertools/commons": "^2.0.2" }, "keywords": [ "aws", diff --git a/packages/metrics/src/Metrics.ts b/packages/metrics/src/Metrics.ts index ad4026f5a3..5b828379b3 100644 --- a/packages/metrics/src/Metrics.ts +++ b/packages/metrics/src/Metrics.ts @@ -1,4 +1,5 @@ import type { Callback, Context, Handler } from 'aws-lambda'; +import { Console } from 'node:console'; import { Utility } from '@aws-lambda-powertools/commons'; import type { HandlerMethodDecorator } from '@aws-lambda-powertools/commons/types'; import { EnvironmentVariablesService } from './config/EnvironmentVariablesService.js'; @@ -48,7 +49,8 @@ import { * * @example * ```typescript - * import { Metrics, logMetrics } from '@aws-lambda-powertools/metrics'; + * import { Metrics } from '@aws-lambda-powertools/metrics'; + * import { logMetrics } from '@aws-lambda-powertools/metrics/middleware'; * import middy from '@middy/core'; * * const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' }); @@ -70,8 +72,8 @@ import { * @example * * ```typescript - * import { Metrics, MetricUnits } from '@aws-lambda-powertools/metrics'; - * import { LambdaInterface } from '@aws-lambda-powertools/commons'; + * import { Metrics, MetricUnit } from '@aws-lambda-powertools/metrics'; + * import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; * * const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' }); * @@ -108,6 +110,18 @@ import { * ``` */ class Metrics extends Utility implements MetricsInterface { + /** + * Console instance used to print logs. + * + * In AWS Lambda, we create a new instance of the Console class so that we can have + * full control over the output of the logs. In testing environments, we use the + * default console instance. + * + * This property is initialized in the constructor in setOptions(). + * + * @private + */ + private console!: Console; private customConfigService?: ConfigServiceInterface; private defaultDimensions: Dimensions = {}; private dimensions: Dimensions = {}; @@ -295,15 +309,14 @@ class Metrics extends Utility implements MetricsInterface { * * ```typescript * import { Metrics } from '@aws-lambda-powertools/metrics'; - * import { LambdaInterface } from '@aws-lambda-powertools/commons'; + * import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; * * const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' }); * * class Lambda implements LambdaInterface { - * * @metrics.logMetrics({ captureColdStartMetric: true }) * public handler(_event: unknown, __context: unknown): Promise { - * // ... + * // ... * } * } * @@ -387,7 +400,7 @@ class Metrics extends Utility implements MetricsInterface { ); } const target = this.serializeMetrics(); - console.log(JSON.stringify(target)); + this.console.log(JSON.stringify(target)); this.clearMetrics(); this.clearDimensions(); this.clearMetadata(); @@ -439,8 +452,10 @@ class Metrics extends Utility implements MetricsInterface { ); const dimensionNames = [ - ...Object.keys(this.defaultDimensions), - ...Object.keys(this.dimensions), + ...new Set([ + ...Object.keys(this.defaultDimensions), + ...Object.keys(this.dimensions), + ]), ]; return { @@ -588,6 +603,24 @@ class Metrics extends Utility implements MetricsInterface { } } + /** + * It initializes console property as an instance of the internal version of Console() class (PR #748) + * or as the global node console if the `POWERTOOLS_DEV' env variable is set and has truthy value. + * + * @private + * @returns {void} + */ + private setConsole(): void { + if (!this.getEnvVarsService().isDevMode()) { + this.console = new Console({ + stdout: process.stdout, + stderr: process.stderr, + }); + } else { + this.console = console; + } + } + /** * Sets the custom config service to be used. * @@ -637,6 +670,7 @@ class Metrics extends Utility implements MetricsInterface { } = options; this.setEnvVarsService(); + this.setConsole(); this.setCustomConfigService(customConfigService); this.setNamespace(namespace); this.setService(serviceName); diff --git a/packages/metrics/src/config/EnvironmentVariablesService.ts b/packages/metrics/src/config/EnvironmentVariablesService.ts index 290b70a571..7ec51b9e7f 100644 --- a/packages/metrics/src/config/EnvironmentVariablesService.ts +++ b/packages/metrics/src/config/EnvironmentVariablesService.ts @@ -7,6 +7,11 @@ class EnvironmentVariablesService { private namespaceVariable = 'POWERTOOLS_METRICS_NAMESPACE'; + /** + * It returns the value of the POWERTOOLS_METRICS_NAMESPACE environment variable. + * + * @returns {string} + */ public getNamespace(): string { return this.get(this.namespaceVariable); } diff --git a/packages/metrics/src/middleware/middy.ts b/packages/metrics/src/middleware/middy.ts index b5c2fa196c..57744b45df 100644 --- a/packages/metrics/src/middleware/middy.ts +++ b/packages/metrics/src/middleware/middy.ts @@ -17,7 +17,8 @@ import type { * * @example * ```typescript - * import { Metrics, logMetrics } from '@aws-lambda-powertools/metrics'; + * import { Metrics } from '@aws-lambda-powertools/metrics'; + * import { logMetrics } from '@aws-lambda-powertools/metrics/middleware'; * import middy from '@middy/core'; * * const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' }); diff --git a/packages/metrics/src/types/ConfigServiceInterface.ts b/packages/metrics/src/types/ConfigServiceInterface.ts index 81842a691d..3f8557f399 100644 --- a/packages/metrics/src/types/ConfigServiceInterface.ts +++ b/packages/metrics/src/types/ConfigServiceInterface.ts @@ -1,7 +1,19 @@ -interface ConfigServiceInterface { - get?(name: string): string; +import type { ConfigServiceInterface as ConfigServiceBaseInterface } from '@aws-lambda-powertools/commons/types'; + +/** + * Interface ConfigServiceInterface + * + * @interface + * @see https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime + * @see https://docs.powertools.aws.dev/lambda/typescript/latest/#environment-variables + */ +interface ConfigServiceInterface extends ConfigServiceBaseInterface { + /** + * It returns the value of the POWERTOOLS_METRICS_NAMESPACE environment variable. + * + * @returns {string} + */ getNamespace(): string; - getServiceName(): string; } export type { ConfigServiceInterface }; diff --git a/packages/metrics/tests/e2e/basicFeatures.decorators.test.ts b/packages/metrics/tests/e2e/basicFeatures.decorators.test.ts index bdaa6b750d..5bf1a38809 100644 --- a/packages/metrics/tests/e2e/basicFeatures.decorators.test.ts +++ b/packages/metrics/tests/e2e/basicFeatures.decorators.test.ts @@ -12,7 +12,7 @@ import { GetMetricStatisticsCommand, } from '@aws-sdk/client-cloudwatch'; import { join } from 'node:path'; -import { getMetrics } from '../helpers/metricsUtils.js'; +import { getMetrics, sortDimensions } from '../helpers/metricsUtils.js'; import { MetricsTestNodejsFunction } from '../helpers/resources.js'; import { commonEnvironmentVars, @@ -98,7 +98,9 @@ describe(`Metrics E2E tests, basic features decorator usage`, () => { expect(coldStartMetrics.Metrics?.length).toBe(1); const coldStartMetric = coldStartMetrics.Metrics?.[0]; - expect(coldStartMetric?.Dimensions).toStrictEqual(expectedDimensions); + expect(sortDimensions(coldStartMetric?.Dimensions)).toStrictEqual( + sortDimensions(expectedDimensions) + ); // Check coldstart metric value const adjustedStartTime = new Date(startTime.getTime() - ONE_MINUTE); @@ -167,7 +169,9 @@ describe(`Metrics E2E tests, basic features decorator usage`, () => { Value: expectedExtraDimension.MyExtraDimension, }, ]; - expect(metric?.Dimensions).toStrictEqual(expectedDimensions); + expect(sortDimensions(metric?.Dimensions)).toStrictEqual( + sortDimensions(expectedDimensions) + ); // Check coldstart metric value const adjustedStartTime = new Date( diff --git a/packages/metrics/tests/e2e/basicFeatures.manual.test.ts b/packages/metrics/tests/e2e/basicFeatures.manual.test.ts index 6cb286c708..8211d6c882 100644 --- a/packages/metrics/tests/e2e/basicFeatures.manual.test.ts +++ b/packages/metrics/tests/e2e/basicFeatures.manual.test.ts @@ -12,7 +12,7 @@ import { GetMetricStatisticsCommand, } from '@aws-sdk/client-cloudwatch'; import { join } from 'node:path'; -import { getMetrics } from '../helpers/metricsUtils.js'; +import { getMetrics, sortDimensions } from '../helpers/metricsUtils.js'; import { MetricsTestNodejsFunction } from '../helpers/resources.js'; import { commonEnvironmentVars, @@ -156,7 +156,9 @@ describe(`Metrics E2E tests, manual usage`, () => { Value: expectedExtraDimension.MyExtraDimension, }, ]; - expect(metric?.Dimensions).toStrictEqual(expectedDimensions); + expect(sortDimensions(metric?.Dimensions)).toStrictEqual( + sortDimensions(expectedDimensions) + ); // Check coldstart metric value const adjustedStartTime = new Date( diff --git a/packages/metrics/tests/e2e/constants.ts b/packages/metrics/tests/e2e/constants.ts index 6cc13e546c..dbffabf33a 100644 --- a/packages/metrics/tests/e2e/constants.ts +++ b/packages/metrics/tests/e2e/constants.ts @@ -4,7 +4,7 @@ import { MetricUnit } from '../../src/index.js'; const RESOURCE_NAME_PREFIX = 'Metrics'; const ONE_MINUTE = 60 * 1000; const TEST_CASE_TIMEOUT = 3 * ONE_MINUTE; -const SETUP_TIMEOUT = 5 * ONE_MINUTE; +const SETUP_TIMEOUT = 7 * ONE_MINUTE; const TEARDOWN_TIMEOUT = 5 * ONE_MINUTE; const commonEnvironmentVars = { diff --git a/packages/metrics/tests/helpers/metricsUtils.ts b/packages/metrics/tests/helpers/metricsUtils.ts index 0984c8a6bc..859c551266 100644 --- a/packages/metrics/tests/helpers/metricsUtils.ts +++ b/packages/metrics/tests/helpers/metricsUtils.ts @@ -5,7 +5,10 @@ import { CloudWatchClient, ListMetricsCommand, } from '@aws-sdk/client-cloudwatch'; -import type { ListMetricsCommandOutput } from '@aws-sdk/client-cloudwatch'; +import type { + Dimension, + ListMetricsCommandOutput, +} from '@aws-sdk/client-cloudwatch'; import type { Context, Handler } from 'aws-lambda'; import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; @@ -64,4 +67,7 @@ const setupDecoratorLambdaHandler = ( return handler; }; -export { getMetrics, setupDecoratorLambdaHandler }; +const sortDimensions = (dimensions?: Dimension[]): Dimension[] | undefined => + dimensions?.sort((a, b) => (a.Name || '').localeCompare(b?.Name || '')); + +export { getMetrics, setupDecoratorLambdaHandler, sortDimensions }; diff --git a/packages/metrics/tests/unit/Metrics.test.ts b/packages/metrics/tests/unit/Metrics.test.ts index b161aab738..a1ee97ac4a 100644 --- a/packages/metrics/tests/unit/Metrics.test.ts +++ b/packages/metrics/tests/unit/Metrics.test.ts @@ -23,6 +23,13 @@ import { import { setupDecoratorLambdaHandler } from '../helpers/metricsUtils.js'; import { EnvironmentVariablesService } from '../../src/config/EnvironmentVariablesService.js'; +jest.mock('node:console', () => ({ + ...jest.requireActual('node:console'), + Console: jest.fn().mockImplementation(() => ({ + log: jest.fn(), + })), +})); +jest.spyOn(console, 'warn').mockImplementation(() => ({})); const mockDate = new Date(1466424490000); const dateSpy = jest.spyOn(global, 'Date').mockImplementation(() => mockDate); jest.spyOn(console, 'log').mockImplementation(); @@ -235,6 +242,15 @@ describe('Class: Metrics', () => { getServiceName(): string { return 'test-service'; }, + getXrayTraceId(): string | undefined { + return 'test-trace-id'; + }, + isDevMode(): boolean { + return false; + }, + isValueTrue(value: string): boolean { + return value === 'true'; + }, }; const metricsOptions: MetricsOptions = { customConfigService: configService, @@ -467,9 +483,7 @@ describe('Class: Metrics', () => { } // Act & Assess - expect(() => - metrics.addDimensions(dimensionsToBeAdded) - ).not.toThrowError(); + metrics.addDimensions(dimensionsToBeAdded); expect(Object.keys(metrics['dimensions']).length).toBe( MAX_DIMENSION_COUNT ); @@ -701,7 +715,7 @@ describe('Class: Metrics', () => { test('it should publish metrics when the array of values reaches the maximum size', () => { // Prepare const metrics: Metrics = new Metrics({ namespace: TEST_NAMESPACE }); - const consoleSpy = jest.spyOn(console, 'log'); + const consoleSpy = jest.spyOn(metrics['console'], 'log'); const metricName = 'test-metric'; // Act @@ -1244,7 +1258,9 @@ describe('Class: Metrics', () => { // Prepare const metrics: Metrics = new Metrics({ namespace: TEST_NAMESPACE }); metrics.addMetric('test-metric', MetricUnit.Count, 10); - const consoleLogSpy = jest.spyOn(console, 'log').mockImplementation(); + const consoleLogSpy = jest + .spyOn(metrics['console'], 'log') + .mockImplementation(); const mockData: EmfOutput = { _aws: { Timestamp: mockDate.getTime(), @@ -1501,6 +1517,53 @@ describe('Class: Metrics', () => { }); }); + test('it should log dimensions once when default dimensions are set and addDimension is called', () => { + // Prepare + const additionalDimensions = { + foo: 'bar', + env: 'dev', + }; + const testMetric = 'test-metric'; + const metrics: Metrics = new Metrics({ + defaultDimensions: additionalDimensions, + namespace: TEST_NAMESPACE, + }); + + // Act + metrics.addMetric(testMetric, MetricUnit.Count, 10); + metrics.addDimension('foo', 'baz'); + const loggedData = metrics.serializeMetrics(); + + // Assess + expect(loggedData._aws.CloudWatchMetrics[0].Dimensions[0].length).toEqual( + 3 + ); + expect(loggedData.service).toEqual(defaultServiceName); + expect(loggedData.foo).toEqual('baz'); + expect(loggedData.env).toEqual(additionalDimensions.env); + expect(loggedData).toEqual({ + _aws: { + CloudWatchMetrics: [ + { + Dimensions: [['service', 'foo', 'env']], + Metrics: [ + { + Name: testMetric, + Unit: MetricUnit.Count, + }, + ], + Namespace: TEST_NAMESPACE, + }, + ], + Timestamp: mockDate.getTime(), + }, + service: 'service_undefined', + [testMetric]: 10, + env: 'dev', + foo: 'baz', + }); + }); + test('it should log additional dimensions correctly', () => { // Prepare const testMetric = 'test-metric'; @@ -2134,4 +2197,15 @@ describe('Class: Metrics', () => { ); }); }); + + describe('Feature: POWERTOOLS_DEV', () => { + it('uses the global console object when the environment variable is set', () => { + // Prepare + process.env.POWERTOOLS_DEV = 'true'; + const metrics: Metrics = new Metrics({ namespace: TEST_NAMESPACE }); + + // Act & Assess + expect(metrics['console']).toEqual(console); + }); + }); }); diff --git a/packages/metrics/tests/unit/middleware/middy.test.ts b/packages/metrics/tests/unit/middleware/middy.test.ts index 57109fd30d..f39d9f8db8 100644 --- a/packages/metrics/tests/unit/middleware/middy.test.ts +++ b/packages/metrics/tests/unit/middleware/middy.test.ts @@ -10,15 +10,22 @@ import { ExtraOptions } from '../../../src/types/index.js'; import { cleanupMiddlewares } from '@aws-lambda-powertools/commons'; import context from '@aws-lambda-powertools/testing-utils/context'; -const consoleSpy = jest.spyOn(console, 'log').mockImplementation(); -const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(); +jest.mock('node:console', () => ({ + ...jest.requireActual('node:console'), + Console: jest.fn().mockImplementation(() => ({ + log: jest.fn(), + })), +})); +jest.spyOn(console, 'warn').mockImplementation(() => ({})); const mockDate = new Date(1466424490000); jest.spyOn(global, 'Date').mockImplementation(() => mockDate); describe('Middy middleware', () => { + const ENVIRONMENT_VARIABLES = process.env; + beforeEach(() => { - jest.resetModules(); jest.clearAllMocks(); + process.env = { ...ENVIRONMENT_VARIABLES }; }); const event = { @@ -33,22 +40,13 @@ describe('Middy middleware', () => { namespace: 'serverlessAirline', serviceName: 'orders', }); - - const lambdaHandler = (): void => { - console.log('do nothing'); - }; - - const handler = middy(lambdaHandler).use( + const handler = middy(async (): Promise => undefined).use( logMetrics(metrics, { throwOnEmptyMetrics: true }) ); - try { - await handler(event, context, () => console.log('Lambda invoked!')); - } catch (e) { - expect((e).message).toBe( - 'The number of metrics recorded must be higher than zero' - ); - } + await expect(handler(event, context)).rejects.toThrowError( + 'The number of metrics recorded must be higher than zero' + ); }); test('should not throw on empty metrics if set to false', async () => { @@ -57,20 +55,12 @@ describe('Middy middleware', () => { namespace: 'serverlessAirline', serviceName: 'orders', }); - - const lambdaHandler = (): void => { - console.log('do nothing'); - }; - - const handler = middy(lambdaHandler).use( + const handler = middy(async (): Promise => undefined).use( logMetrics(metrics, { throwOnEmptyMetrics: false }) ); - try { - await handler(event, context, () => console.log('Lambda invoked!')); - } catch (e) { - fail(`Should not throw but got the following Error: ${e}`); - } + // Act & Assess + await expect(handler(event, context)).resolves.not.toThrowError(); }); test('should not throw on empty metrics if not set, but should log a warning', async () => { @@ -79,10 +69,10 @@ describe('Middy middleware', () => { namespace: 'serverlessAirline', serviceName: 'orders', }); - const lambdaHandler = async (): Promise => { - console.log('do nothing'); - }; - const handler = middy(lambdaHandler).use(logMetrics(metrics)); + const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation(); + const handler = middy(async (): Promise => undefined).use( + logMetrics([metrics]) + ); // Act & Assess await expect(handler(event, context)).resolves.not.toThrowError(); @@ -100,23 +90,27 @@ describe('Middy middleware', () => { namespace: 'serverlessAirline', serviceName: 'orders', }); - - const lambdaHandler = (): void => { - console.log('{"message": "do nothing"}'); - }; - - const handler = middy(lambdaHandler).use( + const consoleSpy = jest + .spyOn(metrics['console'], 'log') + .mockImplementation(); + // Monkey patch the singleMetric method to return the metrics instance + // so that we can assert on the console output + jest.spyOn(metrics, 'singleMetric').mockImplementation(() => metrics); + + const handler = middy(async (): Promise => undefined).use( logMetrics(metrics, { captureColdStartMetric: true }) ); - await handler(event, context, () => console.log('Lambda invoked!')); - await handler(event, context, () => console.log('Lambda invoked! again')); + // Act + await handler(event, context); + await handler(event, context); + + // Assess const loggedData = [ JSON.parse(consoleSpy.mock.calls[0][0]), JSON.parse(consoleSpy.mock.calls[1][0]), ]; - - expect(console.log).toBeCalledTimes(5); + expect(consoleSpy).toBeCalledTimes(2); expect(loggedData[0]._aws.CloudWatchMetrics[0].Metrics.length).toBe(1); expect(loggedData[0]._aws.CloudWatchMetrics[0].Metrics[0].Name).toBe( 'ColdStart' @@ -133,23 +127,23 @@ describe('Middy middleware', () => { namespace: 'serverlessAirline', serviceName: 'orders', }); - - const lambdaHandler = (): void => { - console.log('{"message": "do nothing"}'); - }; - - const handler = middy(lambdaHandler).use( + const consoleSpy = jest + .spyOn(metrics['console'], 'log') + .mockImplementation(); + // Monkey patch the singleMetric method to return the metrics instance + // so that we can assert on the console output + jest.spyOn(metrics, 'singleMetric').mockImplementation(() => metrics); + const handler = middy(async (): Promise => undefined).use( logMetrics(metrics, { captureColdStartMetric: false }) ); - await handler(event, context, () => console.log('Lambda invoked!')); - await handler(event, context, () => console.log('Lambda invoked! again')); - const loggedData = [ - JSON.parse(consoleSpy.mock.calls[0][0]), - JSON.parse(consoleSpy.mock.calls[1][0]), - ]; + // Act + await handler(event, context); + + // Assess + const loggedData = JSON.parse(consoleSpy.mock.calls[0][0]); - expect(loggedData[0]._aws).toBe(undefined); + expect(loggedData._aws.CloudWatchMetrics[0].Metrics.length).toBe(0); }); test('should not throw on empty metrics if not set', async () => { @@ -158,21 +152,12 @@ describe('Middy middleware', () => { namespace: 'serverlessAirline', serviceName: 'orders', }); + const handler = middy(async (): Promise => undefined).use( + logMetrics(metrics) + ); - const lambdaHandler = (): void => { - console.log('{"message": "do nothing"}'); - }; - - const handler = middy(lambdaHandler).use(logMetrics(metrics)); - - await handler(event, context, () => console.log('Lambda invoked!')); - await handler(event, context, () => console.log('Lambda invoked! again')); - const loggedData = [ - JSON.parse(consoleSpy.mock.calls[0][0]), - JSON.parse(consoleSpy.mock.calls[1][0]), - ]; - - expect(loggedData[0]._aws).toBe(undefined); + // Act & Assess + await expect(handler(event, context)).resolves.not.toThrow(); }); }); @@ -183,19 +168,17 @@ describe('Middy middleware', () => { namespace: 'serverlessAirline', serviceName: 'orders', }); - - const lambdaHandler = (): void => { + const consoleSpy = jest.spyOn(metrics['console'], 'log'); + const handler = middy(async (): Promise => { metrics.addMetric('successfulBooking', MetricUnit.Count, 2); metrics.addMetric('successfulBooking', MetricUnit.Count, 1); - }; - - const handler = middy(lambdaHandler).use(logMetrics(metrics)); + }).use(logMetrics(metrics)); // Act - await handler(event, context, () => console.log('Lambda invoked!')); + await handler(event, context); // Assess - expect(console.log).toHaveBeenNthCalledWith( + expect(consoleSpy).toHaveBeenNthCalledWith( 1, JSON.stringify({ _aws: { @@ -220,47 +203,22 @@ describe('Middy middleware', () => { namespace: 'serverlessAirline', serviceName: 'orders', }); - - const lambdaHandler = (): void => { - metrics.addMetric('successfulBooking', MetricUnit.Count, 1); - }; + const consoleSpy = jest.spyOn(metrics['console'], 'log'); const metricsOptions: ExtraOptions = { throwOnEmptyMetrics: true, defaultDimensions: { environment: 'prod', aws_region: 'eu-west-1' }, captureColdStartMetric: true, }; - const handler = middy(lambdaHandler).use( - logMetrics(metrics, metricsOptions) - ); + const handler = middy(async (): Promise => { + metrics.addMetric('successfulBooking', MetricUnit.Count, 1); + }).use(logMetrics(metrics, metricsOptions)); // Act - await handler(event, context, () => console.log('Lambda invoked!')); + await handler(event, context); // Assess - expect(console.log).toHaveBeenNthCalledWith( + expect(consoleSpy).toHaveBeenNthCalledWith( 1, - JSON.stringify({ - _aws: { - Timestamp: 1466424490000, - CloudWatchMetrics: [ - { - Namespace: 'serverlessAirline', - Dimensions: [ - ['service', 'environment', 'aws_region', 'function_name'], - ], - Metrics: [{ Name: 'ColdStart', Unit: 'Count' }], - }, - ], - }, - service: 'orders', - environment: 'prod', - aws_region: 'eu-west-1', - function_name: 'foo-bar-function', - ColdStart: 1, - }) - ); - expect(console.log).toHaveBeenNthCalledWith( - 2, JSON.stringify({ _aws: { Timestamp: 1466424490000, @@ -286,18 +244,16 @@ describe('Middy middleware', () => { namespace: 'serverlessAirline', serviceName: 'orders', }); - - const lambdaHandler = (): void => { + const consoleSpy = jest.spyOn(metrics['console'], 'log'); + const handler = middy(async (): Promise => { metrics.addMetric('successfulBooking', MetricUnit.Count, 1); - }; - - const handler = middy(lambdaHandler).use(logMetrics(metrics)); + }).use(logMetrics(metrics)); // Act - await handler(event, context, () => console.log('Lambda invoked!')); + await handler(event, context); // Assess - expect(console.log).toHaveBeenNthCalledWith( + expect(consoleSpy).toHaveBeenNthCalledWith( 1, JSON.stringify({ _aws: { @@ -322,22 +278,20 @@ describe('Middy middleware', () => { namespace: 'serverlessAirline', serviceName: 'orders', }); - - const lambdaHandler = (): void => { + const consoleSpy = jest.spyOn(metrics['console'], 'log'); + const handler = middy(async (): Promise => { metrics.addMetric('successfulBooking', MetricUnit.Count, 1); - }; - const metricsOptions: ExtraOptions = { - throwOnEmptyMetrics: true, - }; - const handler = middy(lambdaHandler).use( - logMetrics([metrics], metricsOptions) + }).use( + logMetrics(metrics, { + throwOnEmptyMetrics: true, + }) ); // Act - await handler(event, context, () => console.log('Lambda invoked!')); + await handler(event, context); // Assess - expect(console.log).toHaveBeenNthCalledWith( + expect(consoleSpy).toHaveBeenNthCalledWith( 1, JSON.stringify({ _aws: { @@ -408,22 +362,21 @@ describe('Middy middleware', () => { serviceName: 'orders', }); - const lambdaHandler = (): void => { + const consoleSpy = jest.spyOn(metrics['console'], 'log'); + const handler = middy((): void => { metrics.addMetric( 'successfulBooking', MetricUnit.Count, 1, MetricResolution.Standard ); - }; - - const handler = middy(lambdaHandler).use(logMetrics(metrics)); + }).use(logMetrics(metrics)); // Act - await handler(event, context, () => console.log('Lambda invoked!')); + await handler(event, context); // Assess - expect(console.log).toHaveBeenCalledWith( + expect(consoleSpy).toHaveBeenCalledWith( JSON.stringify({ _aws: { Timestamp: 1466424490000, @@ -452,23 +405,21 @@ describe('Middy middleware', () => { namespace: 'serverlessAirline', serviceName: 'orders', }); - - const lambdaHandler = (): void => { + const consoleSpy = jest.spyOn(metrics['console'], 'log'); + const handler = middy((): void => { metrics.addMetric( 'successfulBooking', MetricUnit.Count, 1, MetricResolution.High ); - }; - - const handler = middy(lambdaHandler).use(logMetrics(metrics)); + }).use(logMetrics(metrics)); // Act - await handler(event, context, () => console.log('Lambda invoked!')); + await handler(event, context); // Assess - expect(console.log).toHaveBeenCalledWith( + expect(consoleSpy).toHaveBeenCalledWith( JSON.stringify({ _aws: { Timestamp: 1466424490000, diff --git a/packages/parameters/CHANGELOG.md b/packages/parameters/CHANGELOG.md index fbe040eb52..3dfe4174c3 100644 --- a/packages/parameters/CHANGELOG.md +++ b/packages/parameters/CHANGELOG.md @@ -3,6 +3,67 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2.0.2 (2024-03-05) + +**Note:** Version bump only for package @aws-lambda-powertools/parameters + + + + + + +## 2.0.1 (2024-03-04) + +**Note:** Version bump only for package @aws-lambda-powertools/parameters + + + + + +# [2.0.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.18.1...v2.0.0) (2024-03-04) + +**Note:** Version bump only for package @aws-lambda-powertools/parameters + + + + + +## 1.18.1 (2024-02-20) + +**Note:** Version bump only for package @aws-lambda-powertools/parameters + + + + + +## [1.18.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.17.0...v1.18.0) (2024-01-26) + +### Bug Fixes + +- **parameters:** refresh AppConfig session token after 24 hrs ([#1916](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1916)) ([559ef2d](https://github.com/aws-powertools/powertools-lambda-typescript/commit/559ef2dd0d012cb8c4e378b2a1457a6f52885a17)) + +## [1.17.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.16.0...v1.17.0) (2023-11-24) + +**maintenance:** drop support for Node.js 14 ([#1664](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1664)) ([e2a0923](https://github.com/aws-powertools/powertools-lambda-typescript/commit/e2a09232f86167b5208be2daf892aa1ea433ce0f)) + +# [1.16.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.15.0...v1.16.0) (2023-11-16) + +**Note:** Version bump only for package @aws-lambda-powertools/parameters + +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) + +## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) + +**Note:** Version bump only for package @aws-lambda-powertools/parameters + +## [1.14.1](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.0...v1.14.1) (2023-10-31) + +**Note:** Version bump only for package @aws-lambda-powertools/parameters + # [1.14.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.13.1...v1.14.0) (2023-09-29) ### Features diff --git a/packages/parameters/README.md b/packages/parameters/README.md index 080bd9751e..a00bc6ff19 100644 --- a/packages/parameters/README.md +++ b/packages/parameters/README.md @@ -230,6 +230,8 @@ The following companies, among others, use Powertools: * [Sennder](https://sennder.com/) * [Certible](https://www.certible.com/) * [tecRacer GmbH & Co. KG](https://www.tecracer.com/) +* [AppYourself](https://appyourself.net) +* [Alma Media](https://www.almamedia.fi) ### Sharing your work diff --git a/packages/parameters/package.json b/packages/parameters/package.json index 5448c0ff69..ba05a0d60b 100644 --- a/packages/parameters/package.json +++ b/packages/parameters/package.json @@ -1,6 +1,6 @@ { "name": "@aws-lambda-powertools/parameters", - "version": "1.14.0", + "version": "2.0.2", "description": "The parameters package for the Powertools for AWS Lambda (TypeScript) library", "author": { "name": "Amazon Web Services", @@ -15,6 +15,7 @@ "jest": "jest --detectOpenHandles --verbose", "test:e2e:nodejs16x": "RUNTIME=nodejs16x jest --group=e2e", "test:e2e:nodejs18x": "RUNTIME=nodejs18x jest --group=e2e", + "test:e2e:nodejs20x": "RUNTIME=nodejs20x jest --group=e2e", "test:e2e": "jest --group=e2e", "watch": "jest --watch", "build:cjs": "tsc --build tsconfig.json && echo '{ \"type\": \"commonjs\" }' > lib/cjs/package.json", @@ -157,16 +158,16 @@ ], "devDependencies": { "@aws-lambda-powertools/testing-utils": "file:../testing", - "@aws-sdk/client-appconfigdata": "^3.438.0", - "@aws-sdk/client-dynamodb": "^3.438.0", - "@aws-sdk/client-secrets-manager": "^3.438.0", - "@aws-sdk/client-ssm": "^3.438.0", - "@aws-sdk/util-dynamodb": "^3.438.0", - "aws-sdk-client-mock": "^3.0.0", - "aws-sdk-client-mock-jest": "^3.0.0" + "@aws-sdk/client-appconfigdata": "^3.525.0", + "@aws-sdk/client-dynamodb": "^3.525.0", + "@aws-sdk/client-secrets-manager": "^3.525.0", + "@aws-sdk/client-ssm": "^3.525.0", + "@aws-sdk/util-dynamodb": "^3.525.0", + "aws-sdk-client-mock": "^3.0.1", + "aws-sdk-client-mock-jest": "^3.0.1" }, "dependencies": { - "@aws-lambda-powertools/commons": "^1.14.0", + "@aws-lambda-powertools/commons": "^2.0.2", "@aws-sdk/util-base64-node": "^3.209.0" }, "peerDependencies": { diff --git a/packages/parameters/src/appconfig/AppConfigProvider.ts b/packages/parameters/src/appconfig/AppConfigProvider.ts index 6fae54a564..4a77a19e99 100644 --- a/packages/parameters/src/appconfig/AppConfigProvider.ts +++ b/packages/parameters/src/appconfig/AppConfigProvider.ts @@ -10,6 +10,7 @@ import type { AppConfigGetOptions, AppConfigGetOutput, } from '../types/AppConfigProvider.js'; +import { APPCONFIG_TOKEN_EXPIRATION } from '../constants.js'; /** * ## Intro @@ -178,11 +179,14 @@ import type { * * This object must be an instance of the [AWS SDK v3 for JavaScript AppConfig Data client](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-appconfigdata/classes/appconfigdataclient.html). * - * For more usage examples, see [our documentation](https://docs.powertools.aws.dev/lambda-typescript/latest/utilities/parameters/). + * For more usage examples, see [our documentation](https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parameters/). */ class AppConfigProvider extends BaseProvider { public declare client: AppConfigDataClient; - protected configurationTokenStore = new Map(); + protected configurationTokenStore = new Map< + string, + { value: string; expiration: number } + >(); protected valueStore = new Map(); private application?: string; private environment: string; @@ -240,7 +244,7 @@ class AppConfigProvider extends BaseProvider { * * @param {string} name - The name of the configuration profile or its ID * @param {AppConfigGetOptions} options - Options to configure the provider - * @see https://docs.powertools.aws.dev/lambda-typescript/latest/utilities/parameters/ + * @see https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parameters/ */ public async get< ExplicitUserProvidedType = undefined, @@ -270,6 +274,15 @@ class AppConfigProvider extends BaseProvider { /** * Retrieve a configuration from AWS AppConfig. * + * First we start the session and after that we retrieve the configuration from AppSync. + * When starting a session, the service returns a token that can be used to poll for changes + * for up to 24hrs, so we cache it for later use together with the expiration date. + * + * The value of the configuration is also cached internally because AppConfig returns an empty + * value if the configuration has not changed since the last poll. This way even if your code + * polls the configuration multiple times, we return the most recent value by returning the cached + * one if an empty response is returned by AppConfig. + * * @param {string} name - Name of the configuration or its ID * @param {AppConfigGetOptions} options - SDK options to propagate to `StartConfigurationSession` API call */ @@ -277,16 +290,10 @@ class AppConfigProvider extends BaseProvider { name: string, options?: AppConfigGetOptions ): Promise { - /** - * The new AppConfig APIs require two API calls to return the configuration - * First we start the session and after that we retrieve the configuration - * We need to store { name: token } pairs to use in the next execution - * We also need to store { name : value } pairs because AppConfig returns - * an empty value if the session already has the latest configuration - * but, we don't want to return an empty value to our callers. - * {@link https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-retrieving-the-configuration.html} - **/ - if (!this.configurationTokenStore.has(name)) { + if ( + !this.configurationTokenStore.has(name) || + this.configurationTokenStore.get(name)!.expiration <= Date.now() + ) { const sessionOptions: StartConfigurationSessionCommandInput = { ...(options?.sdkOptions || {}), ApplicationIdentifier: this.application, @@ -303,20 +310,23 @@ class AppConfigProvider extends BaseProvider { if (!session.InitialConfigurationToken) throw new Error('Unable to retrieve the configuration token'); - this.configurationTokenStore.set(name, session.InitialConfigurationToken); + this.configurationTokenStore.set(name, { + value: session.InitialConfigurationToken, + expiration: Date.now() + APPCONFIG_TOKEN_EXPIRATION, + }); } const getConfigurationCommand = new GetLatestConfigurationCommand({ - ConfigurationToken: this.configurationTokenStore.get(name), + ConfigurationToken: this.configurationTokenStore.get(name)?.value, }); const response = await this.client.send(getConfigurationCommand); if (response.NextPollConfigurationToken) { - this.configurationTokenStore.set( - name, - response.NextPollConfigurationToken - ); + this.configurationTokenStore.set(name, { + value: response.NextPollConfigurationToken, + expiration: Date.now() + APPCONFIG_TOKEN_EXPIRATION, + }); } else { this.configurationTokenStore.delete(name); } diff --git a/packages/parameters/src/base/index.ts b/packages/parameters/src/base/index.ts index 9705d1348d..760ba42344 100644 --- a/packages/parameters/src/base/index.ts +++ b/packages/parameters/src/base/index.ts @@ -1,4 +1,4 @@ export { BaseProvider } from './BaseProvider.js'; -export { DEFAULT_PROVIDERS, clearCaches } from './DefaultProviders.js'; +export { DEFAULT_PROVIDERS } from './DefaultProviders.js'; export { GetOptions } from './GetOptions.js'; export { GetMultipleOptions } from './GetMultipleOptions.js'; diff --git a/packages/parameters/src/config/EnvironmentVariablesService.ts b/packages/parameters/src/config/EnvironmentVariablesService.ts index 23744e7483..b0c39e9bf3 100644 --- a/packages/parameters/src/config/EnvironmentVariablesService.ts +++ b/packages/parameters/src/config/EnvironmentVariablesService.ts @@ -10,6 +10,11 @@ class EnvironmentVariablesService private parametersMaxAgeVariable = 'POWERTOOLS_PARAMETERS_MAX_AGE'; private ssmDecryptVariable = 'POWERTOOLS_PARAMETERS_SSM_DECRYPT'; + /** + * It returns the value of the POWERTOOLS_PARAMETERS_MAX_AGE environment variable. + * + * @returns {number|undefined} + */ public getParametersMaxAge(): number | undefined { const maxAge = this.get(this.parametersMaxAgeVariable); @@ -25,6 +30,11 @@ class EnvironmentVariablesService } } + /** + * It returns the value of the POWERTOOLS_PARAMETERS_SSM_DECRYPT environment variable. + * + * @returns {string} + */ public getSSMDecrypt(): string { return this.get(this.ssmDecryptVariable); } diff --git a/packages/parameters/src/constants.ts b/packages/parameters/src/constants.ts index dcb53165c7..4855b5bb4e 100644 --- a/packages/parameters/src/constants.ts +++ b/packages/parameters/src/constants.ts @@ -2,6 +2,7 @@ const DEFAULT_MAX_AGE_SECS = 5; const TRANSFORM_METHOD_JSON = 'json'; const TRANSFORM_METHOD_BINARY = 'binary'; const TRANSFORM_METHOD_AUTO = 'auto'; +const APPCONFIG_TOKEN_EXPIRATION = 23 * 60 * 60 * 1000 + 45 * 60 * 1000; // 23 hrs 45 min /** * Transform methods for values retrieved by parameter providers. @@ -22,6 +23,7 @@ const Transform = { } as const; export { + APPCONFIG_TOKEN_EXPIRATION, DEFAULT_MAX_AGE_SECS, TRANSFORM_METHOD_JSON, TRANSFORM_METHOD_BINARY, diff --git a/packages/parameters/src/dynamodb/DynamoDBProvider.ts b/packages/parameters/src/dynamodb/DynamoDBProvider.ts index 0076ac0436..566635a626 100644 --- a/packages/parameters/src/dynamodb/DynamoDBProvider.ts +++ b/packages/parameters/src/dynamodb/DynamoDBProvider.ts @@ -3,6 +3,7 @@ import { DynamoDBClient, GetItemCommand, paginateQuery, + type DynamoDBPaginationConfiguration, } from '@aws-sdk/client-dynamodb'; import { marshall, unmarshall } from '@aws-sdk/util-dynamodb'; import type { @@ -16,7 +17,6 @@ import type { GetItemCommandInput, QueryCommandInput, } from '@aws-sdk/client-dynamodb'; -import type { PaginationConfiguration } from '@aws-sdk/types'; import type { JSONValue } from '@aws-lambda-powertools/commons/types'; /** @@ -232,7 +232,7 @@ import type { JSONValue } from '@aws-lambda-powertools/commons/types'; * * This object must be an instance of the [AWS SDK v3 for JavaScript DynamoDB client](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-dynamodb/classes/dynamodbclient.html). * - * For more usage examples, see [our documentation](https://docs.powertools.aws.dev/lambda-typescript/latest/utilities/parameters/). + * For more usage examples, see [our documentation](https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parameters/). */ class DynamoDBProvider extends BaseProvider { public declare client: DynamoDBClient; @@ -287,7 +287,7 @@ class DynamoDBProvider extends BaseProvider { * * @param {string} name - The name of the value to retrieve (i.e. the partition key) * @param {DynamoDBGetOptionsInterface} options - Options to configure the provider - * @see https://docs.powertools.aws.dev/lambda-typescript/latest/utilities/parameters/ + * @see https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parameters/ */ public async get< ExplicitUserProvidedType = undefined, @@ -335,7 +335,7 @@ class DynamoDBProvider extends BaseProvider { * * @param {string} path - The path of the values to retrieve (i.e. the partition key) * @param {DynamoDBGetMultipleOptions} options - Options to configure the provider - * @see https://docs.powertools.aws.dev/lambda-typescript/latest/utilities/parameters/ + * @see https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parameters/ */ public async getMultiple< ExplicitUserProvidedType = undefined, @@ -407,7 +407,7 @@ class DynamoDBProvider extends BaseProvider { }, ProjectionExpression: '#sk, #value', }; - const paginationOptions: PaginationConfiguration = { + const paginationOptions: DynamoDBPaginationConfiguration = { client: this.client, pageSize: options?.sdkOptions?.Limit, }; diff --git a/packages/parameters/src/index.ts b/packages/parameters/src/index.ts index 89b255eb5c..58580e1e1a 100644 --- a/packages/parameters/src/index.ts +++ b/packages/parameters/src/index.ts @@ -1,2 +1,3 @@ +export { clearCaches } from './base/DefaultProviders.js'; export { GetParameterError, TransformParameterError } from './errors.js'; export { Transform } from './constants.js'; diff --git a/packages/parameters/src/ssm/SSMProvider.ts b/packages/parameters/src/ssm/SSMProvider.ts index 4bdfdf9c6c..787bd8915c 100644 --- a/packages/parameters/src/ssm/SSMProvider.ts +++ b/packages/parameters/src/ssm/SSMProvider.ts @@ -13,6 +13,7 @@ import type { GetParametersByPathCommandInput, GetParametersCommandInput, GetParametersCommandOutput, + SSMPaginationConfiguration, } from '@aws-sdk/client-ssm'; import type { SSMProviderOptions, @@ -26,7 +27,6 @@ import type { SSMSplitBatchAndDecryptParametersOutputType, SSMGetParametersByNameFromCacheOutputType, } from '../types/SSMProvider.js'; -import type { PaginationConfiguration } from '@aws-sdk/types'; /** * ## Intro @@ -259,7 +259,7 @@ import type { PaginationConfiguration } from '@aws-sdk/types'; * * This object must be an instance of the [AWS SDK v3 for JavaScript SSM client](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-ssm/classes/ssmclient.html). * - * For more usage examples, see [our documentation](https://docs.powertools.aws.dev/lambda-typescript/latest/utilities/parameters/). + * For more usage examples, see [our documentation](https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parameters/). */ class SSMProvider extends BaseProvider { public declare client: SSMClient; @@ -304,7 +304,7 @@ class SSMProvider extends BaseProvider { * * @param {string} name - The name of the value to retrieve (i.e. the partition key) * @param {SSMGetOptions} options - Options to configure the provider - * @see https://docs.powertools.aws.dev/lambda-typescript/latest/utilities/parameters/ + * @see https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parameters/ */ public async get< ExplicitUserProvidedType = undefined, @@ -349,7 +349,7 @@ class SSMProvider extends BaseProvider { * * @param {string} path - The path of the parameters to retrieve * @param {SSMGetMultipleOptions} options - Options to configure the retrieval - * @see https://docs.powertools.aws.dev/lambda-typescript/latest/utilities/parameters/ + * @see https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parameters/ */ public async getMultiple< ExplicitUserProvidedType = undefined, @@ -417,7 +417,7 @@ class SSMProvider extends BaseProvider { * * @param {Record} parameters - Object containing parameter names and any optional overrides * @param {SSMGetParametersByNameOptions} options - Options to configure the retrieval - * @see https://docs.powertools.aws.dev/lambda-typescript/latest/utilities/parameters/ + * @see https://docs.powertools.aws.dev/lambda/typescript/latest/utilities/parameters/ */ public async getParametersByName( parameters: Record, @@ -524,7 +524,7 @@ class SSMProvider extends BaseProvider { ...(options?.sdkOptions || {}), Path: path, }; - const paginationOptions: PaginationConfiguration = { + const paginationOptions: SSMPaginationConfiguration = { client: this.client, }; sdkOptions.WithDecryption = this.resolveDecryptionConfigValue( diff --git a/packages/parameters/src/types/AppConfigProvider.ts b/packages/parameters/src/types/AppConfigProvider.ts index b5ebd576c7..64dc4ee170 100644 --- a/packages/parameters/src/types/AppConfigProvider.ts +++ b/packages/parameters/src/types/AppConfigProvider.ts @@ -115,12 +115,12 @@ type AppConfigGetOutput< ? undefined extends InferredFromOptionsType | AppConfigGetOptionsTransformNone ? Uint8Array : InferredFromOptionsType extends AppConfigGetOptionsTransformNone - ? Uint8Array - : InferredFromOptionsType extends AppConfigGetOptionsTransformBinary - ? string - : InferredFromOptionsType extends AppConfigGetOptionsTransformJson - ? JSONValue - : never + ? Uint8Array + : InferredFromOptionsType extends AppConfigGetOptionsTransformBinary + ? string + : InferredFromOptionsType extends AppConfigGetOptionsTransformJson + ? JSONValue + : never : ExplicitUserProvidedType; /** diff --git a/packages/parameters/src/types/ConfigServiceInterface.ts b/packages/parameters/src/types/ConfigServiceInterface.ts index 2baf93974d..c05f1856a0 100644 --- a/packages/parameters/src/types/ConfigServiceInterface.ts +++ b/packages/parameters/src/types/ConfigServiceInterface.ts @@ -1,10 +1,24 @@ -interface ConfigServiceInterface { - get?(name: string): string; - - getServiceName(): string; +import type { ConfigServiceInterface as ConfigServiceBaseInterface } from '@aws-lambda-powertools/commons/types'; +/** + * Interface ConfigServiceInterface + * + * @interface + * @see https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime + * @see https://docs.powertools.aws.dev/lambda/typescript/latest/#environment-variables + */ +interface ConfigServiceInterface extends ConfigServiceBaseInterface { + /** + * It returns the value of the POWERTOOLS_PARAMETERS_MAX_AGE environment variable. + * + * @returns {number|undefined} + */ getParametersMaxAge(): number | undefined; - + /** + * It returns the value of the POWERTOOLS_PARAMETERS_SSM_DECRYPT environment variable. + * + * @returns {string} + */ getSSMDecrypt(): string; } diff --git a/packages/parameters/src/types/DynamoDBProvider.ts b/packages/parameters/src/types/DynamoDBProvider.ts index 198dd508b9..97b6241636 100644 --- a/packages/parameters/src/types/DynamoDBProvider.ts +++ b/packages/parameters/src/types/DynamoDBProvider.ts @@ -120,12 +120,12 @@ type DynamoDBGetOutput< ? undefined extends InferredFromOptionsType ? JSONValue : InferredFromOptionsType extends - | DynamoDBGetOptionsTransformNone - | DynamoDBGetOptionsTransformJson - ? JSONValue - : InferredFromOptionsType extends DynamoDBGetOptionsTransformBinary - ? string - : never + | DynamoDBGetOptionsTransformNone + | DynamoDBGetOptionsTransformJson + ? JSONValue + : InferredFromOptionsType extends DynamoDBGetOptionsTransformBinary + ? string + : never : ExplicitUserProvidedType; /** @@ -179,13 +179,13 @@ type DynamoDBGetMultipleOutput< ? undefined extends InferredFromOptionsType ? JSONValue : InferredFromOptionsType extends - | DynamoDBGetMultipleOptionsTransformNone - | DynamoDBGetMultipleOptionsTransformAuto - | DynamoDBGetMultipleOptionsTransformJson - ? JSONValue - : InferredFromOptionsType extends DynamoDBGetOptionsTransformBinary - ? string - : never + | DynamoDBGetMultipleOptionsTransformNone + | DynamoDBGetMultipleOptionsTransformAuto + | DynamoDBGetMultipleOptionsTransformJson + ? JSONValue + : InferredFromOptionsType extends DynamoDBGetOptionsTransformBinary + ? string + : never : ExplicitUserProvidedType; export type { diff --git a/packages/parameters/src/types/SSMProvider.ts b/packages/parameters/src/types/SSMProvider.ts index 45ae2de225..b647fe29c9 100644 --- a/packages/parameters/src/types/SSMProvider.ts +++ b/packages/parameters/src/types/SSMProvider.ts @@ -104,12 +104,12 @@ type SSMGetOutput< ? undefined extends InferredFromOptionsType ? string : InferredFromOptionsType extends - | SSMGetOptionsTransformNone - | SSMGetOptionsTransformBinary - ? string - : InferredFromOptionsType extends SSMGetOptionsTransformJson - ? JSONValue - : never + | SSMGetOptionsTransformNone + | SSMGetOptionsTransformBinary + ? string + : InferredFromOptionsType extends SSMGetOptionsTransformJson + ? JSONValue + : never : ExplicitUserProvidedType; /** @@ -178,14 +178,14 @@ type SSMGetMultipleOutput< ? undefined extends InferredFromOptionsType ? Record : InferredFromOptionsType extends - | SSMGetMultipleOptionsTransformNone - | SSMGetMultipleOptionsTransformBinary - ? Record - : InferredFromOptionsType extends SSMGetMultipleOptionsTransformAuto - ? Record - : InferredFromOptionsType extends SSMGetMultipleOptionsTransformJson - ? Record - : never + | SSMGetMultipleOptionsTransformNone + | SSMGetMultipleOptionsTransformBinary + ? Record + : InferredFromOptionsType extends SSMGetMultipleOptionsTransformAuto + ? Record + : InferredFromOptionsType extends SSMGetMultipleOptionsTransformJson + ? Record + : never : Record; /** diff --git a/packages/parameters/src/types/SecretsProvider.ts b/packages/parameters/src/types/SecretsProvider.ts index 223756503a..9e2c492f3b 100644 --- a/packages/parameters/src/types/SecretsProvider.ts +++ b/packages/parameters/src/types/SecretsProvider.ts @@ -94,12 +94,12 @@ type SecretsGetOutput< ? undefined extends InferredFromOptionsType ? string | Uint8Array : InferredFromOptionsType extends SecretsGetOptionsTransformNone - ? string | Uint8Array - : InferredFromOptionsType extends SecretsGetOptionsTransformBinary - ? string - : InferredFromOptionsType extends SecretsGetOptionsTransformJson - ? JSONValue - : never + ? string | Uint8Array + : InferredFromOptionsType extends SecretsGetOptionsTransformBinary + ? string + : InferredFromOptionsType extends SecretsGetOptionsTransformJson + ? JSONValue + : never : ExplicitUserProvidedType; export type { SecretsProviderOptions, SecretsGetOptions, SecretsGetOutput }; diff --git a/packages/parameters/tests/e2e/constants.ts b/packages/parameters/tests/e2e/constants.ts index 757a2b4290..b9b9e6ef30 100644 --- a/packages/parameters/tests/e2e/constants.ts +++ b/packages/parameters/tests/e2e/constants.ts @@ -1,5 +1,5 @@ export const RESOURCE_NAME_PREFIX = 'Parameters'; export const ONE_MINUTE = 60 * 1000; export const TEST_CASE_TIMEOUT = 3 * ONE_MINUTE; -export const SETUP_TIMEOUT = 5 * ONE_MINUTE; +export const SETUP_TIMEOUT = 7 * ONE_MINUTE; export const TEARDOWN_TIMEOUT = 5 * ONE_MINUTE; diff --git a/packages/parameters/tests/unit/AppConfigProvider.test.ts b/packages/parameters/tests/unit/AppConfigProvider.test.ts index b2f5844402..71881d3c48 100644 --- a/packages/parameters/tests/unit/AppConfigProvider.test.ts +++ b/packages/parameters/tests/unit/AppConfigProvider.test.ts @@ -15,11 +15,13 @@ import { Uint8ArrayBlobAdapter } from '@smithy/util-stream'; import { mockClient } from 'aws-sdk-client-mock'; import { addUserAgentMiddleware } from '@aws-lambda-powertools/commons'; import 'aws-sdk-client-mock-jest'; +import { APPCONFIG_TOKEN_EXPIRATION } from '../../src/constants'; jest.mock('@aws-lambda-powertools/commons', () => ({ ...jest.requireActual('@aws-lambda-powertools/commons'), addUserAgentMiddleware: jest.fn(), })); +jest.useFakeTimers(); describe('Class: AppConfigProvider', () => { const client = mockClient(AppConfigDataClient); @@ -201,7 +203,10 @@ describe('Class: AppConfigProvider', () => { // Prepare class AppConfigProviderMock extends AppConfigProvider { public _addToStore(key: string, value: string): void { - this.configurationTokenStore.set(key, value); + this.configurationTokenStore.set(key, { + value, + expiration: Date.now() + APPCONFIG_TOKEN_EXPIRATION, + }); } public _storeHas(key: string): boolean { @@ -289,6 +294,56 @@ describe('Class: AppConfigProvider', () => { expect(result1).toBe(mockData); expect(result2).toBe(mockData); }); + + test('when the session token has expired, it starts a new session and retrieves the token', async () => { + // Prepare + const options: AppConfigProviderOptions = { + application: 'MyApp', + environment: 'MyAppProdEnv', + }; + const provider = new AppConfigProvider(options); + const name = 'MyAppFeatureFlag'; + + const fakeInitialToken = 'aW5pdGlhbFRva2Vu'; + const fakeSecondToken = 'bZ6pdGlhbFRva3Wk'; + const fakeNextToken1 = 'bmV4dFRva2Vu'; + const mockData = Uint8ArrayBlobAdapter.fromString('foo'); + const mockData2 = Uint8ArrayBlobAdapter.fromString('bar'); + + client + .on(StartConfigurationSessionCommand) + .resolvesOnce({ + InitialConfigurationToken: fakeInitialToken, + }) + .resolvesOnce({ + InitialConfigurationToken: fakeSecondToken, + }) + .on(GetLatestConfigurationCommand, { + ConfigurationToken: fakeInitialToken, + }) + .resolves({ + Configuration: mockData, + NextPollConfigurationToken: fakeNextToken1, + }) + .on(GetLatestConfigurationCommand, { + ConfigurationToken: fakeSecondToken, + }) + .resolves({ + Configuration: mockData2, + NextPollConfigurationToken: fakeNextToken1, + }); + jest.setSystemTime(new Date('2022-03-10')); + + // Act + const result1 = await provider.get(name, { forceFetch: true }); + // Mock time skip of 24hrs + jest.setSystemTime(new Date('2022-03-11')); + const result2 = await provider.get(name, { forceFetch: true }); + + // Assess + expect(result1).toBe(mockData); + expect(result2).toBe(mockData2); + }); }); describe('Method: _getMultiple', () => { diff --git a/packages/parameters/tests/unit/BaseProvider.test.ts b/packages/parameters/tests/unit/BaseProvider.test.ts index 0c2a923fbb..18e87bb0dc 100644 --- a/packages/parameters/tests/unit/BaseProvider.test.ts +++ b/packages/parameters/tests/unit/BaseProvider.test.ts @@ -5,7 +5,6 @@ */ import { BaseProvider, - clearCaches, DEFAULT_PROVIDERS, GetOptions, GetMultipleOptions, @@ -13,7 +12,11 @@ import { import { DEFAULT_MAX_AGE_SECS } from '../../src/constants.js'; import type { EnvironmentVariablesService } from '../../src/config/EnvironmentVariablesService.js'; import { ExpirableValue } from '../../src/base/ExpirableValue.js'; -import { GetParameterError, TransformParameterError } from '../../src/index.js'; +import { + GetParameterError, + TransformParameterError, + clearCaches, +} from '../../src/index.js'; import { toBase64 } from '@aws-sdk/util-base64-node'; const encoder = new TextEncoder(); diff --git a/packages/parser/package.json b/packages/parser/package.json index fe89ba9c5c..947b633e19 100644 --- a/packages/parser/package.json +++ b/packages/parser/package.json @@ -39,16 +39,40 @@ } }, "./middleware": { - "import": "./lib/esm/parser.js", - "require": "./lib/cjs/parser.js" + "require": "./lib/cjs/middleware/parser.js", + "import": "./lib/esm/middleware/parser.js" }, "./schemas": { - "import": "./lib/esm/index.js", - "require": "./lib/cjs/index.js" + "require": "./lib/cjs/schemas/index.js", + "import": "./lib/esm/schemas/index.js" }, "./envelopes": { - "import": "./lib/esm/index.js", - "require": "./lib/cjs/index.js" + "require": "./lib/cjs/envelopes/index.js", + "import": "./lib/esm/envelopes/index.js" + }, + "./types": { + "require": "./lib/cjs/types/index.js", + "import": "./lib/esm/types/index.js" + } + }, + "typesVersions": { + "*": { + "types": [ + "./lib/cjs/types/index.d.ts", + "./lib/esm/types/index.d.ts" + ], + "middleware": [ + "./lib/cjs/middleware/parser.d.ts", + "./lib/esm/middleware/parser.d.ts" + ], + "schemas": [ + "./lib/cjs/schemas/index.d.ts", + "./lib/esm/schemas/index.d.ts" + ], + "envelopes": [ + "./lib/cjs/envelopes/index.d.ts", + "./lib/esm/envelopes/index.d.ts" + ] } }, "main": "./lib/cjs/index.js", diff --git a/packages/parser/src/envelopes/apigw.ts b/packages/parser/src/envelopes/apigw.ts index 49d094b405..ee4d71e9c0 100644 --- a/packages/parser/src/envelopes/apigw.ts +++ b/packages/parser/src/envelopes/apigw.ts @@ -1,18 +1,40 @@ -import { parse } from './envelope.js'; -import { z, ZodSchema } from 'zod'; +import { Envelope } from './envelope.js'; +import { z, type ZodSchema } from 'zod'; import { APIGatewayProxyEventSchema } from '../schemas/apigw.js'; +import type { ParsedResult } from '../types/parser.js'; /** * API Gateway envelope to extract data within body key */ -export const apiGatewayEnvelope = ( - data: unknown, - schema: T -): z.infer => { - const parsedEnvelope = APIGatewayProxyEventSchema.parse(data); - if (!parsedEnvelope.body) { - throw new Error('Body field of API Gateway event is undefined'); +export class ApiGatewayEnvelope extends Envelope { + public static parse( + data: unknown, + schema: T + ): z.infer { + return super.parse(APIGatewayProxyEventSchema.parse(data).body, schema); } - return parse(parsedEnvelope.body, schema); -}; + public static safeParse( + data: unknown, + schema: T + ): ParsedResult> { + const parsedEnvelope = APIGatewayProxyEventSchema.safeParse(data); + if (!parsedEnvelope.success) { + return { + ...parsedEnvelope, + originalEvent: data, + }; + } + + const parsedBody = super.safeParse(parsedEnvelope.data.body, schema); + + if (!parsedBody.success) { + return { + ...parsedBody, + originalEvent: data, + }; + } + + return parsedBody; + } +} diff --git a/packages/parser/src/envelopes/apigwv2.ts b/packages/parser/src/envelopes/apigwv2.ts index decadfcc57..3da86e26e4 100644 --- a/packages/parser/src/envelopes/apigwv2.ts +++ b/packages/parser/src/envelopes/apigwv2.ts @@ -1,18 +1,40 @@ -import { parse } from './envelope.js'; -import { z, ZodSchema } from 'zod'; +import { z, type ZodSchema } from 'zod'; import { APIGatewayProxyEventV2Schema } from '../schemas/apigwv2.js'; +import { Envelope } from './envelope.js'; +import type { ParsedResult } from '../types/index.js'; /** * API Gateway V2 envelope to extract data within body key */ -export const apiGatewayV2Envelope = ( - data: unknown, - schema: T -): z.infer => { - const parsedEnvelope = APIGatewayProxyEventV2Schema.parse(data); - if (!parsedEnvelope.body) { - throw new Error('Body field of API Gateway event is undefined'); +export class ApiGatewayV2Envelope extends Envelope { + public static parse( + data: unknown, + schema: T + ): z.infer { + return super.parse(APIGatewayProxyEventV2Schema.parse(data).body, schema); } - return parse(parsedEnvelope.body, schema); -}; + public static safeParse( + data: unknown, + schema: T + ): ParsedResult { + const parsedEnvelope = APIGatewayProxyEventV2Schema.safeParse(data); + if (!parsedEnvelope.success) { + return { + ...parsedEnvelope, + originalEvent: data, + }; + } + + const parsedBody = super.safeParse(parsedEnvelope.data.body, schema); + + if (!parsedBody.success) { + return { + ...parsedBody, + originalEvent: data, + }; + } + + return parsedBody; + } +} diff --git a/packages/parser/src/envelopes/cloudwatch.ts b/packages/parser/src/envelopes/cloudwatch.ts index 848e7ab070..f90e6455f9 100644 --- a/packages/parser/src/envelopes/cloudwatch.ts +++ b/packages/parser/src/envelopes/cloudwatch.ts @@ -1,6 +1,7 @@ -import { parse } from './envelope.js'; -import { z, ZodSchema } from 'zod'; -import { CloudWatchLogsSchema } from '../schemas/cloudwatch.js'; +import { z, type ZodSchema } from 'zod'; +import { Envelope } from './envelope.js'; +import { CloudWatchLogsSchema } from '../schemas/index.js'; +import type { ParsedResult } from '../types/index.js'; /** * CloudWatch Envelope to extract a List of log records. @@ -11,13 +12,49 @@ import { CloudWatchLogsSchema } from '../schemas/cloudwatch.js'; * * Note: The record will be parsed the same way so if model is str */ -export const cloudWatchEnvelope = ( - data: unknown, - schema: T -): z.infer => { - const parsedEnvelope = CloudWatchLogsSchema.parse(data); +export class CloudWatchEnvelope extends Envelope { + public static parse( + data: unknown, + schema: T + ): z.infer { + const parsedEnvelope = CloudWatchLogsSchema.parse(data); - return parsedEnvelope.awslogs.data.logEvents.map((record) => { - return parse(record.message, schema); - }); -}; + return parsedEnvelope.awslogs.data.logEvents.map((record) => { + return super.parse(record.message, schema); + }); + } + + public static safeParse( + data: unknown, + schema: T + ): ParsedResult { + const parsedEnvelope = CloudWatchLogsSchema.safeParse(data); + + if (!parsedEnvelope.success) { + return { + success: false, + error: parsedEnvelope.error, + originalEvent: data, + }; + } + const parsedLogEvents: z.infer[] = []; + + for (const record of parsedEnvelope.data.awslogs.data.logEvents) { + const parsedMessage = super.safeParse(record.message, schema); + if (!parsedMessage.success) { + return { + success: false, + error: parsedMessage.error, + originalEvent: data, + }; + } else { + parsedLogEvents.push(parsedMessage.data); + } + } + + return { + success: true, + data: parsedLogEvents, + }; + } +} diff --git a/packages/parser/src/envelopes/dynamodb.ts b/packages/parser/src/envelopes/dynamodb.ts index 1dca32fb33..4898369422 100644 --- a/packages/parser/src/envelopes/dynamodb.ts +++ b/packages/parser/src/envelopes/dynamodb.ts @@ -1,6 +1,7 @@ -import { parse } from './envelope.js'; -import { z, ZodSchema } from 'zod'; -import { DynamoDBStreamSchema } from '../schemas/dynamodb.js'; +import { z, type ZodSchema } from 'zod'; +import { DynamoDBStreamSchema } from '../schemas/index.js'; +import type { ParsedResult, ParsedResultError } from '../types/index.js'; +import { Envelope } from './envelope.js'; type DynamoDBStreamEnvelopeResponse = { NewImage: z.infer; @@ -13,16 +14,58 @@ type DynamoDBStreamEnvelopeResponse = { * Note: Values are the parsed models. Images' values can also be None, and * length of the list is the record's amount in the original event. */ -export const dynamoDBStreamEnvelope = ( - data: unknown, - schema: T -): DynamoDBStreamEnvelopeResponse[] => { - const parsedEnvelope = DynamoDBStreamSchema.parse(data); +export class DynamoDBStreamEnvelope extends Envelope { + public static parse( + data: unknown, + schema: T + ): DynamoDBStreamEnvelopeResponse>[] { + const parsedEnvelope = DynamoDBStreamSchema.parse(data); + + return parsedEnvelope.Records.map((record) => { + return { + NewImage: super.parse(record.dynamodb.NewImage, schema), + OldImage: super.parse(record.dynamodb.OldImage, schema), + }; + }); + } + + public static safeParse( + data: unknown, + schema: T + ): ParsedResult { + const parsedEnvelope = DynamoDBStreamSchema.safeParse(data); + + if (!parsedEnvelope.success) { + return { + success: false, + error: parsedEnvelope.error, + originalEvent: data, + }; + } + const parsedLogEvents: DynamoDBStreamEnvelopeResponse>[] = []; + + for (const record of parsedEnvelope.data.Records) { + const parsedNewImage = super.safeParse(record.dynamodb.NewImage, schema); + const parsedOldImage = super.safeParse(record.dynamodb.OldImage, schema); + if (!parsedNewImage.success || !parsedOldImage.success) { + return { + success: false, + error: !parsedNewImage.success + ? parsedNewImage.error + : (parsedOldImage as ParsedResultError).error, + originalEvent: data, + }; + } else { + parsedLogEvents.push({ + NewImage: parsedNewImage.data, + OldImage: parsedOldImage.data, + }); + } + } - return parsedEnvelope.Records.map((record) => { return { - NewImage: parse(record.dynamodb.NewImage, schema), - OldImage: parse(record.dynamodb.OldImage, schema), + success: true, + data: parsedLogEvents, }; - }); -}; + } +} diff --git a/packages/parser/src/envelopes/envelope.ts b/packages/parser/src/envelopes/envelope.ts index 4c2dd9570d..ed55758153 100644 --- a/packages/parser/src/envelopes/envelope.ts +++ b/packages/parser/src/envelopes/envelope.ts @@ -1,23 +1,70 @@ -import { z, ZodSchema } from 'zod'; +import { z, type ZodSchema } from 'zod'; +import type { ParsedResult } from '../types/parser.js'; -/** - * Abstract function to parse the content of the envelope using provided schema. - * Both inputs are provided as unknown by the user. - * We expect the data to be either string that can be parsed to json or object. - * @internal - * @param data data to parse - * @param schema schema - */ -export const parse = ( - data: unknown, - schema: T -): z.infer[] => { - if (typeof data === 'string') { - return schema.parse(JSON.parse(data)); - } else if (typeof data === 'object') { - return schema.parse(data); - } else - throw new Error( - `Invalid data type for envelope. Expected string or object, got ${typeof data}` - ); -}; +export class Envelope { + /** + * Abstract function to parse the content of the envelope using provided schema. + * Both inputs are provided as unknown by the user. + * We expect the data to be either string that can be parsed to json or object. + * @internal + * @param data data to parse + * @param schema schema + */ + public static readonly parse = ( + data: unknown, + schema: T + ): z.infer => { + if (typeof data === 'string') { + return schema.parse(JSON.parse(data)); + } else if (typeof data === 'object') { + return schema.parse(data); + } else + throw new Error( + `Invalid data type for envelope. Expected string or object, got ${typeof data}` + ); + }; + + /** + * Abstract function to safely parse the content of the envelope using provided schema. + * safeParse is used to avoid throwing errors, thus we catuch all errors and wrap them in the result. + * @param input + * @param schema + */ + public static readonly safeParse = ( + input: unknown, + schema: T + ): ParsedResult> => { + try { + if (typeof input !== 'object' && typeof input !== 'string') { + return { + success: false, + error: new Error( + `Invalid data type for envelope. Expected string or object, got ${typeof input}` + ), + originalEvent: input, + }; + } + + const parsed = schema.safeParse( + typeof input === 'string' ? JSON.parse(input) : input + ); + + return parsed.success + ? { + success: true, + data: parsed.data, + } + : { + success: false, + error: parsed.error, + originalEvent: input, + }; + } catch (e) { + return { + success: false, + error: e as Error, + originalEvent: input, + }; + } + }; +} diff --git a/packages/parser/src/envelopes/event-bridge.ts b/packages/parser/src/envelopes/event-bridge.ts index 4484635348..0d166d673b 100644 --- a/packages/parser/src/envelopes/event-bridge.ts +++ b/packages/parser/src/envelopes/event-bridge.ts @@ -1,13 +1,41 @@ -import { parse } from './envelope.js'; -import { z, ZodSchema } from 'zod'; -import { EventBridgeSchema } from '../schemas/eventbridge.js'; +import { Envelope } from './envelope.js'; +import { z, type ZodSchema } from 'zod'; +import { EventBridgeSchema } from '../schemas/index.js'; +import type { ParsedResult } from '../types/index.js'; /** * Envelope for EventBridge schema that extracts and parses data from the `detail` key. */ -export const eventBridgeEnvelope = ( - data: unknown, - schema: T -): z.infer => { - return parse(EventBridgeSchema.parse(data).detail, schema); -}; +export class EventBridgeEnvelope extends Envelope { + public static parse( + data: unknown, + schema: T + ): z.infer { + return super.parse(EventBridgeSchema.parse(data).detail, schema); + } + + public static safeParse( + data: unknown, + schema: T + ): ParsedResult { + const parsedEnvelope = EventBridgeSchema.safeParse(data); + + if (!parsedEnvelope.success) { + return { + ...parsedEnvelope, + originalEvent: data, + }; + } + + const parsedDetail = super.safeParse(parsedEnvelope.data.detail, schema); + + if (!parsedDetail.success) { + return { + ...parsedDetail, + originalEvent: data, + }; + } + + return parsedDetail; + } +} diff --git a/packages/parser/src/envelopes/index.ts b/packages/parser/src/envelopes/index.ts index 0ff3615920..3d1487a7b0 100644 --- a/packages/parser/src/envelopes/index.ts +++ b/packages/parser/src/envelopes/index.ts @@ -1,13 +1,13 @@ -export { apiGatewayEnvelope } from './apigw.js'; -export { apiGatewayV2Envelope } from './apigwv2.js'; -export { cloudWatchEnvelope } from './cloudwatch.js'; -export { dynamoDBStreamEnvelope } from './dynamodb.js'; -export { eventBridgeEnvelope } from './event-bridge.js'; -export { kafkaEnvelope } from './kafka.js'; -export { kinesisEnvelope } from './kinesis.js'; -export { kinesisFirehoseEnvelope } from './kinesis-firehose.js'; -export { lambdaFunctionUrlEnvelope } from './lambda.js'; -export { snsEnvelope, snsSqsEnvelope } from './sns.js'; -export { sqsEnvelope } from './sqs.js'; -export { vpcLatticeEnvelope } from './vpc-lattice.js'; -export { vpcLatticeV2Envelope } from './vpc-latticev2.js'; +export { ApiGatewayEnvelope } from './apigw.js'; +export { ApiGatewayV2Envelope } from './apigwv2.js'; +export { CloudWatchEnvelope } from './cloudwatch.js'; +export { DynamoDBStreamEnvelope } from './dynamodb.js'; +export { EventBridgeEnvelope } from './event-bridge.js'; +export { KafkaEnvelope } from './kafka.js'; +export { KinesisEnvelope } from './kinesis.js'; +export { KinesisFirehoseEnvelope } from './kinesis-firehose.js'; +export { LambdaFunctionUrlEnvelope } from './lambda.js'; +export { SnsEnvelope, SnsSqsEnvelope } from './sns.js'; +export { SqsEnvelope } from './sqs.js'; +export { VpcLatticeEnvelope } from './vpc-lattice.js'; +export { VpcLatticeV2Envelope } from './vpc-latticev2.js'; diff --git a/packages/parser/src/envelopes/kafka.ts b/packages/parser/src/envelopes/kafka.ts index 32529d4255..1bbd442f3f 100644 --- a/packages/parser/src/envelopes/kafka.ts +++ b/packages/parser/src/envelopes/kafka.ts @@ -1,10 +1,10 @@ -import { z, ZodSchema } from 'zod'; -import { parse } from './envelope.js'; +import { z, type ZodSchema } from 'zod'; +import { Envelope } from './envelope.js'; import { KafkaMskEventSchema, KafkaSelfManagedEventSchema, } from '../schemas/kafka.js'; -import { type KafkaRecord } from '../types/schema.js'; +import { ParsedResult, KafkaMskEvent } from '../types/index.js'; /** * Kafka event envelope to extract data within body key @@ -14,26 +14,66 @@ import { type KafkaRecord } from '../types/schema.js'; * Note: Records will be parsed the same way so if model is str, * all items in the list will be parsed as str and not as JSON (and vice versa) */ -export const kafkaEnvelope = ( - data: unknown, - schema: T -): z.infer => { - // manually fetch event source to deside between Msk or SelfManaged - - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - const eventSource = data['eventSource']; - - const parsedEnvelope: - | z.infer - | z.infer = - eventSource === 'aws:kafka' - ? KafkaMskEventSchema.parse(data) - : KafkaSelfManagedEventSchema.parse(data); - - return Object.values(parsedEnvelope.records).map((topicRecord) => { - return topicRecord.map((record: KafkaRecord) => { - return parse(record.value, schema); + +export class KafkaEnvelope extends Envelope { + public static parse( + data: unknown, + schema: T + ): z.infer { + // manually fetch event source to deside between Msk or SelfManaged + const eventSource = (data as KafkaMskEvent)['eventSource']; + + const parsedEnvelope: + | z.infer + | z.infer = + eventSource === 'aws:kafka' + ? KafkaMskEventSchema.parse(data) + : KafkaSelfManagedEventSchema.parse(data); + + return Object.values(parsedEnvelope.records).map((topicRecord) => { + return topicRecord.map((record) => { + return super.parse(record.value, schema); + }); }); - }); -}; + } + + public static safeParse( + data: unknown, + schema: T + ): ParsedResult { + // manually fetch event source to deside between Msk or SelfManaged + const eventSource = (data as KafkaMskEvent)['eventSource']; + + const parsedEnvelope = + eventSource === 'aws:kafka' + ? KafkaMskEventSchema.safeParse(data) + : KafkaSelfManagedEventSchema.safeParse(data); + + if (!parsedEnvelope.success) { + return { + ...parsedEnvelope, + originalEvent: data, + }; + } + const parsedRecords: z.infer[] = []; + + for (const topicRecord of Object.values(parsedEnvelope.data.records)) { + for (const record of topicRecord) { + const parsedRecord = super.safeParse(record.value, schema); + if (!parsedRecord.success) { + return { + success: false, + error: parsedRecord.error, + originalEvent: data, + }; + } + parsedRecords.push(parsedRecord.data); + } + } + + return { + success: true, + data: parsedRecords, + }; + } +} diff --git a/packages/parser/src/envelopes/kinesis-firehose.ts b/packages/parser/src/envelopes/kinesis-firehose.ts index e51ae47a12..7dca3cae73 100644 --- a/packages/parser/src/envelopes/kinesis-firehose.ts +++ b/packages/parser/src/envelopes/kinesis-firehose.ts @@ -1,6 +1,7 @@ -import { parse } from './envelope.js'; -import { z, ZodSchema } from 'zod'; -import { KinesisFirehoseSchema } from '../schemas/kinesis-firehose.js'; +import { z, type ZodSchema } from 'zod'; +import { Envelope } from './envelope.js'; +import { KinesisFirehoseSchema } from '../schemas/index.js'; +import type { ParsedResult } from '../types/index.js'; /** * Kinesis Firehose Envelope to extract array of Records @@ -14,13 +15,47 @@ import { KinesisFirehoseSchema } from '../schemas/kinesis-firehose.js'; * * https://docs.aws.amazon.com/lambda/latest/dg/services-kinesisfirehose.html */ -export const kinesisFirehoseEnvelope = ( - data: unknown, - schema: T -): z.infer => { - const parsedEnvelope = KinesisFirehoseSchema.parse(data); +export class KinesisFirehoseEnvelope extends Envelope { + public static parse( + data: unknown, + schema: T + ): z.infer { + const parsedEnvelope = KinesisFirehoseSchema.parse(data); - return parsedEnvelope.records.map((record) => { - return parse(record.data, schema); - }); -}; + return parsedEnvelope.records.map((record) => { + return super.parse(record.data, schema); + }); + } + + public static safeParse( + data: unknown, + schema: T + ): ParsedResult { + const parsedEnvelope = KinesisFirehoseSchema.safeParse(data); + + if (!parsedEnvelope.success) { + return { + ...parsedEnvelope, + originalEvent: data, + }; + } + const parsedRecords: z.infer[] = []; + + for (const record of parsedEnvelope.data.records) { + const parsedData = super.safeParse(record.data, schema); + if (!parsedData.success) { + return { + success: false, + error: parsedData.error, + originalEvent: data, + }; + } + parsedRecords.push(parsedData.data); + } + + return { + success: true, + data: parsedRecords, + }; + } +} diff --git a/packages/parser/src/envelopes/kinesis.ts b/packages/parser/src/envelopes/kinesis.ts index 311223042d..470df40522 100644 --- a/packages/parser/src/envelopes/kinesis.ts +++ b/packages/parser/src/envelopes/kinesis.ts @@ -1,6 +1,7 @@ -import { parse } from './envelope.js'; -import { z, ZodSchema } from 'zod'; +import { Envelope } from './envelope.js'; +import { z, type ZodSchema } from 'zod'; import { KinesisDataStreamSchema } from '../schemas/kinesis.js'; +import type { ParsedResult } from '../types/index.js'; /** * Kinesis Data Stream Envelope to extract array of Records @@ -12,13 +13,46 @@ import { KinesisDataStreamSchema } from '../schemas/kinesis.js'; * Note: Records will be parsed the same way so if model is str, * all items in the list will be parsed as str and not as JSON (and vice versa) */ -export const kinesisEnvelope = ( - data: unknown, - schema: T -): z.infer => { - const parsedEnvelope = KinesisDataStreamSchema.parse(data); +export class KinesisEnvelope extends Envelope { + public static parse( + data: unknown, + schema: T + ): z.infer { + const parsedEnvelope = KinesisDataStreamSchema.parse(data); - return parsedEnvelope.Records.map((record) => { - return parse(record.kinesis.data, schema); - }); -}; + return parsedEnvelope.Records.map((record) => { + return super.parse(record.kinesis.data, schema); + }); + } + + public static safeParse( + data: unknown, + schema: T + ): ParsedResult { + const parsedEnvelope = KinesisDataStreamSchema.safeParse(data); + if (!parsedEnvelope.success) { + return { + ...parsedEnvelope, + originalEvent: data, + }; + } + + const parsedRecords: z.infer[] = []; + + for (const record of parsedEnvelope.data.Records) { + const parsedRecord = super.safeParse(record.kinesis.data, schema); + if (!parsedRecord.success) { + return { + ...parsedRecord, + originalEvent: data, + }; + } + parsedRecords.push(parsedRecord.data); + } + + return { + success: true, + data: parsedRecords, + }; + } +} diff --git a/packages/parser/src/envelopes/lambda.ts b/packages/parser/src/envelopes/lambda.ts index 3ac1f2b8c6..a839c68287 100644 --- a/packages/parser/src/envelopes/lambda.ts +++ b/packages/parser/src/envelopes/lambda.ts @@ -1,18 +1,46 @@ -import { parse } from './envelope.js'; -import { z, ZodSchema } from 'zod'; -import { LambdaFunctionUrlSchema } from '../schemas/lambda.js'; +import { Envelope } from './envelope.js'; +import { z, type ZodSchema } from 'zod'; +import { LambdaFunctionUrlSchema } from '../schemas/index.js'; +import type { ParsedResult } from '../types/index.js'; /** * Lambda function URL envelope to extract data within body key */ -export const lambdaFunctionUrlEnvelope = ( - data: unknown, - schema: T -): z.infer => { - const parsedEnvelope = LambdaFunctionUrlSchema.parse(data); - if (!parsedEnvelope.body) { - throw new Error('Body field of Lambda function URL event is undefined'); +export class LambdaFunctionUrlEnvelope extends Envelope { + public static parse( + data: unknown, + schema: T + ): z.infer { + const parsedEnvelope = LambdaFunctionUrlSchema.parse(data); + + if (!parsedEnvelope.body) { + throw new Error('Body field of Lambda function URL event is undefined'); + } + + return super.parse(parsedEnvelope.body, schema); } - return parse(parsedEnvelope.body, schema); -}; + public static safeParse( + data: unknown, + schema: T + ): ParsedResult { + const parsedEnvelope = LambdaFunctionUrlSchema.safeParse(data); + + if (!parsedEnvelope.success) { + return { + ...parsedEnvelope, + originalEvent: data, + }; + } + + const parsedBody = super.safeParse(parsedEnvelope.data.body, schema); + if (!parsedBody.success) { + return { + ...parsedBody, + originalEvent: data, + }; + } + + return parsedBody; + } +} diff --git a/packages/parser/src/envelopes/sns.ts b/packages/parser/src/envelopes/sns.ts index 3e897a00a8..1141dff305 100644 --- a/packages/parser/src/envelopes/sns.ts +++ b/packages/parser/src/envelopes/sns.ts @@ -1,7 +1,8 @@ -import { z, ZodSchema } from 'zod'; -import { parse } from './envelope.js'; +import { z, type ZodSchema } from 'zod'; +import { Envelope } from './envelope.js'; import { SnsSchema, SnsSqsNotificationSchema } from '../schemas/sns.js'; import { SqsSchema } from '../schemas/sqs.js'; +import type { ParsedResult } from '../types/index.js'; /** * SNS Envelope to extract array of Records @@ -12,16 +13,49 @@ import { SqsSchema } from '../schemas/sqs.js'; * Note: Records will be parsed the same way so if model is str, * all items in the list will be parsed as str and npt as JSON (and vice versa) */ -export const snsEnvelope = ( - data: unknown, - schema: T -): z.infer => { - const parsedEnvelope = SnsSchema.parse(data); +export class SnsEnvelope extends Envelope { + public static parse( + data: unknown, + schema: T + ): z.infer { + const parsedEnvelope = SnsSchema.parse(data); - return parsedEnvelope.Records.map((record) => { - return parse(record.Sns.Message, schema); - }); -}; + return parsedEnvelope.Records.map((record) => { + return super.parse(record.Sns.Message, schema); + }); + } + + public static safeParse( + data: unknown, + schema: T + ): ParsedResult { + const parsedEnvelope = SnsSchema.safeParse(data); + + if (!parsedEnvelope.success) { + return { + ...parsedEnvelope, + originalEvent: data, + }; + } + + const parsedMessages: z.infer[] = []; + for (const record of parsedEnvelope.data.Records) { + const parsedMessage = super.safeParse(record.Sns.Message, schema); + if (!parsedMessage.success) { + return { + ...parsedMessage, + originalEvent: data, + }; + } + parsedMessages.push(parsedMessage.data); + } + + return { + success: true, + data: parsedMessages, + }; + } +} /** * SNS plus SQS Envelope to extract array of Records @@ -34,17 +68,68 @@ export const snsEnvelope = ( * 3. Finally, parse provided model against payload extracted * */ -export const snsSqsEnvelope = ( - data: unknown, - schema: T -): z.infer => { - const parsedEnvelope = SqsSchema.parse(data); - - return parsedEnvelope.Records.map((record) => { - const snsNotification = SnsSqsNotificationSchema.parse( - JSON.parse(record.body) - ); - - return parse(snsNotification.Message, schema); - }); -}; +export class SnsSqsEnvelope extends Envelope { + public static parse( + data: unknown, + schema: T + ): z.infer { + const parsedEnvelope = SqsSchema.parse(data); + + return parsedEnvelope.Records.map((record) => { + const snsNotification = SnsSqsNotificationSchema.parse( + JSON.parse(record.body) + ); + + return super.parse(snsNotification.Message, schema); + }); + } + + public static safeParse( + data: unknown, + schema: T + ): ParsedResult { + const parsedEnvelope = SqsSchema.safeParse(data); + if (!parsedEnvelope.success) { + return { + ...parsedEnvelope, + originalEvent: data, + }; + } + + const parsedMessages: z.infer[] = []; + + // JSON.parse can throw an error, thus we catch it and return ParsedErrorResult + try { + for (const record of parsedEnvelope.data.Records) { + const snsNotification = SnsSqsNotificationSchema.safeParse( + JSON.parse(record.body) + ); + if (!snsNotification.success) { + return { + ...snsNotification, + originalEvent: data, + }; + } + const parsedMessage = super.safeParse( + snsNotification.data.Message, + schema + ); + if (!parsedMessage.success) { + return { + ...parsedMessage, + originalEvent: data, + }; + } + parsedMessages.push(parsedMessage.data); + } + } catch (e) { + return { + success: false, + error: e as Error, + originalEvent: data, + }; + } + + return { success: true, data: parsedMessages }; + } +} diff --git a/packages/parser/src/envelopes/sqs.ts b/packages/parser/src/envelopes/sqs.ts index 2757663a95..b1c8f6c059 100644 --- a/packages/parser/src/envelopes/sqs.ts +++ b/packages/parser/src/envelopes/sqs.ts @@ -1,6 +1,7 @@ -import { z, ZodSchema } from 'zod'; +import { z, type ZodSchema } from 'zod'; import { SqsSchema } from '../schemas/sqs.js'; -import { parse } from './envelope.js'; +import { Envelope } from './envelope.js'; +import type { ParsedResult } from '../types/index.js'; /** * SQS Envelope to extract array of Records @@ -11,13 +12,42 @@ import { parse } from './envelope.js'; * Note: Records will be parsed the same way so if model is str, * all items in the list will be parsed as str and npt as JSON (and vice versa) */ -export const sqsEnvelope = ( - data: unknown, - schema: T -): z.infer => { - const parsedEnvelope = SqsSchema.parse(data); +export class SqsEnvelope extends Envelope { + public static parse( + data: unknown, + schema: T + ): z.infer { + const parsedEnvelope = SqsSchema.parse(data); - return parsedEnvelope.Records.map((record) => { - return parse(record.body, schema); - }); -}; + return parsedEnvelope.Records.map((record) => { + return super.parse(record.body, schema); + }); + } + + public static safeParse( + data: unknown, + schema: T + ): ParsedResult { + const parsedEnvelope = SqsSchema.safeParse(data); + if (!parsedEnvelope.success) { + return { + ...parsedEnvelope, + originalEvent: data, + }; + } + + const parsedRecords: z.infer[] = []; + for (const record of parsedEnvelope.data.Records) { + const parsedRecord = super.safeParse(record.body, schema); + if (!parsedRecord.success) { + return { + ...parsedRecord, + originalEvent: data, + }; + } + parsedRecords.push(parsedRecord.data); + } + + return { success: true, data: parsedRecords }; + } +} diff --git a/packages/parser/src/envelopes/vpc-lattice.ts b/packages/parser/src/envelopes/vpc-lattice.ts index 03d2998757..a7150dd5a4 100644 --- a/packages/parser/src/envelopes/vpc-lattice.ts +++ b/packages/parser/src/envelopes/vpc-lattice.ts @@ -1,15 +1,43 @@ -import { parse } from './envelope.js'; -import { z, ZodSchema } from 'zod'; -import { VpcLatticeSchema } from '../schemas/vpc-lattice.js'; +import { z, type ZodSchema } from 'zod'; +import { Envelope } from './envelope.js'; +import { VpcLatticeSchema } from '../schemas/index.js'; +import type { ParsedResult } from '../types/index.js'; /** * Amazon VPC Lattice envelope to extract data within body key */ -export const vpcLatticeEnvelope = ( - data: unknown, - schema: T -): z.infer => { - const parsedEnvelope = VpcLatticeSchema.parse(data); - - return parse(parsedEnvelope.body, schema); -}; + +export class VpcLatticeEnvelope extends Envelope { + public static parse( + data: unknown, + schema: T + ): z.infer { + const parsedEnvelope = VpcLatticeSchema.parse(data); + + return super.parse(parsedEnvelope.body, schema); + } + + public static safeParse( + data: unknown, + schema: T + ): ParsedResult { + const parsedEnvelope = VpcLatticeSchema.safeParse(data); + if (!parsedEnvelope.success) { + return { + ...parsedEnvelope, + originalEvent: data, + }; + } + + const parsedBody = super.safeParse(parsedEnvelope.data.body, schema); + + if (!parsedBody.success) { + return { + ...parsedBody, + originalEvent: data, + }; + } + + return parsedBody; + } +} diff --git a/packages/parser/src/envelopes/vpc-latticev2.ts b/packages/parser/src/envelopes/vpc-latticev2.ts index a3fa4389c0..7ef31b0702 100644 --- a/packages/parser/src/envelopes/vpc-latticev2.ts +++ b/packages/parser/src/envelopes/vpc-latticev2.ts @@ -1,15 +1,42 @@ -import { parse } from './envelope.js'; -import { z, ZodSchema } from 'zod'; -import { VpcLatticeV2Schema } from '../schemas/vpc-latticev2.js'; +import { Envelope } from './envelope.js'; +import { z, type ZodSchema } from 'zod'; +import { VpcLatticeV2Schema } from '../schemas/index.js'; +import type { ParsedResult } from '../types/index.js'; /** * Amazon VPC Lattice envelope to extract data within body key */ -export const vpcLatticeV2Envelope = ( - data: unknown, - schema: T -): z.infer => { - const parsedEnvelope = VpcLatticeV2Schema.parse(data); - - return parse(parsedEnvelope.body, schema); -}; +export class VpcLatticeV2Envelope extends Envelope { + public static parse( + data: unknown, + schema: T + ): z.infer { + const parsedEnvelope = VpcLatticeV2Schema.parse(data); + + return super.parse(parsedEnvelope.body, schema); + } + + public static safeParse( + data: unknown, + schema: T + ): ParsedResult { + const parsedEnvelope = VpcLatticeV2Schema.safeParse(data); + if (!parsedEnvelope.success) { + return { + ...parsedEnvelope, + originalEvent: data, + }; + } + + const parsedBody = super.safeParse(parsedEnvelope.data.body, schema); + + if (!parsedBody.success) { + return { + ...parsedBody, + originalEvent: data, + }; + } + + return parsedBody; + } +} diff --git a/packages/parser/src/index.ts b/packages/parser/src/index.ts index bb7ee75eb5..940216fe90 100644 --- a/packages/parser/src/index.ts +++ b/packages/parser/src/index.ts @@ -1 +1 @@ -export { parser } from './parser.js'; +export { parser } from './parserDecorator.js'; diff --git a/packages/parser/src/middleware/parser.ts b/packages/parser/src/middleware/parser.ts index 8a2c26c327..0c536b0aeb 100644 --- a/packages/parser/src/middleware/parser.ts +++ b/packages/parser/src/middleware/parser.ts @@ -1,7 +1,8 @@ import { type MiddyLikeRequest } from '@aws-lambda-powertools/commons/types'; import { type MiddlewareObj } from '@middy/core'; import { type ZodSchema } from 'zod'; -import { type ParserOptions } from '../types/ParserOptions.js'; +import { type ParserOptions } from '../types/parser.js'; +import { parse } from '../parser.js'; /** * A middiy middleware to parse your event. @@ -35,12 +36,9 @@ const parser = ( options: ParserOptions ): MiddlewareObj => { const before = (request: MiddyLikeRequest): void => { - const { schema, envelope } = options; - if (envelope) { - request.event = envelope(request.event, schema); - } else { - request.event = schema.parse(request.event); - } + const { schema, envelope, safeParse } = options; + + request.event = parse(request.event, envelope, schema, safeParse); }; return { diff --git a/packages/parser/src/parser.ts b/packages/parser/src/parser.ts index c3ba727ae3..89ed2e4ffb 100644 --- a/packages/parser/src/parser.ts +++ b/packages/parser/src/parser.ts @@ -1,59 +1,66 @@ -import { HandlerMethodDecorator } from '@aws-lambda-powertools/commons/types'; -import { Context, Handler } from 'aws-lambda'; -import { ZodSchema } from 'zod'; -import { type ParserOptions } from './types/ParserOptions.js'; +import type { ParsedResult, Envelope } from './types/index.js'; +import { z, type ZodSchema } from 'zod'; /** - * A decorator to parse your event. + * Parse the data using the provided schema, envelope and safeParse flag * * @example * ```typescript - * - * import { parser } from '@aws-lambda-powertools/parser'; - * import { sqsEnvelope } from '@aws-lambda-powertools/parser/envelopes/sqs'; - * + * import { z } from 'zod'; + * import type { SqsEvent, ParsedResult } from '@aws-lambda-powertools/parser/types'; + * import { SqsEnvelope } from '@aws-lambda-powertools/parser/types/envelopes'; + * import { parse } from '@aws-lambda-powertools/parser'; * * const Order = z.object({ - * orderId: z.string(), - * description: z.string(), - * } + * orderId: z.string(), + * description: z.string(), + * }); * - * class Lambda extends LambdaInterface { + * const handler = async (event: SqsEvent, context: unknown): Promise => { + * const parsedEvent = parse(event, SqsEnvelope, Order); * - * @parser({ envelope: sqsEnvelope, schema: OrderSchema }) - * public async handler(event: Order, _context: Context): Promise { - * // sqs event is parsed and the payload is extracted and parsed - * // apply business logic to your Order event - * const res = processOrder(event); - * return res; - * } + * const parsedSafe: ParsedResult = parse(event, SqsEnvelope, Order, true) * } - * - * @param options + * @param data the data to parse + * @param envelope the envelope to use, can be undefined + * @param schema the schema to use + * @param safeParse whether to use safeParse or not, if true it will return a ParsedResult with the original event if the parsing fails */ -const parser = ( - options: ParserOptions -): HandlerMethodDecorator => { - return (_target, _propertyKey, descriptor) => { - const original = descriptor.value!; +const parse = ( + data: z.infer, + envelope: E | undefined, + schema: T, + safeParse?: boolean +): ParsedResult | z.infer => { + if (envelope && safeParse) { + return envelope.safeParse(data, schema); + } + if (envelope) { + return envelope.parse(data, schema); + } + if (safeParse) { + return safeParseSchema(data, schema); + } - const { schema, envelope } = options; - - descriptor.value = async function ( - this: Handler, - event: unknown, - context: Context, - callback - ) { - const parsedEvent = envelope - ? envelope(event, schema) - : schema.parse(event); + return schema.parse(data); +}; - return original.call(this, parsedEvent, context, callback); - }; +/** + * Parse the data safely using the provided schema. + * This function will not throw an error if the parsing fails, instead it will return a ParsedResultError with the original event. + * Otherwise, it will return ParsedResultSuccess with the parsed data. + * @param data the data to parse + * @param schema the zod schema to use + */ +const safeParseSchema = ( + data: z.infer, + schema: T +): ParsedResult => { + const result = schema.safeParse(data); - return descriptor; - }; + return result.success + ? result + : { success: false, error: result.error, originalEvent: data }; }; -export { parser }; +export { parse }; diff --git a/packages/parser/src/parserDecorator.ts b/packages/parser/src/parserDecorator.ts new file mode 100644 index 0000000000..0572d3a22e --- /dev/null +++ b/packages/parser/src/parserDecorator.ts @@ -0,0 +1,94 @@ +import type { HandlerMethodDecorator } from '@aws-lambda-powertools/commons/types'; +import type { Context, Handler } from 'aws-lambda'; +import { ZodSchema, z } from 'zod'; +import { parse } from './parser.js'; +import type { ParserOptions, ParsedResult } from './types/index.js'; + +/** + * A decorator to parse your event. + * + * @example + * ```typescript + * import { z } from 'zod'; + * import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; + * import type { SqSEvent } from '@aws-lambda-powertools/parser/types; + * import { parser } from '@aws-lambda-powertools/parser'; + * import { SqsEnvelope } from '@aws-lambda-powertools/parser/envelopes'; + * + * const Order = z.object({ + * orderId: z.string(), + * description: z.string(), + * }); + * + * class Lambda implements LambdaInterface { + * + * ⁣@parser({ envelope: SqsEnvelope, schema: OrderSchema }) + * public async handler(event: Order, _context: Context): Promise { + * // sqs event is parsed and the payload is extracted and parsed + * // apply business logic to your Order event + * const res = processOrder(event); + * return res; + * } + * } + * + * ``` + * + * In case you want to parse the event and handle the error, you can use the safeParse option. + * The safeParse option will return an object with the parsed event and an error object if the parsing fails. + * + * @example + * ```typescript + * + * import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; + * import type { SqSEvent, ParsedResult } from '@aws-lambda-powertools/parser/types; + * import { z } from 'zod'; + * import { parser } from '@aws-lambda-powertools/parser'; + * import { SqsEnvelope } from '@aws-lambda-powertools/parser/envelopes'; + * + * + * const Order = z.object({ + * orderId: z.string(), + * description: z.string(), + * } + * + * class Lambda implements LambdaInterface { + * + * ⁣git@parser({ envelope: SqsEnvelope, schema: OrderSchema, safeParse: true }) + * public async handler(event: ParsedResult, _context: unknown): Promise { + * if (event.success) { + * // event.data is the parsed event object of type Order + * } else { + * // event.error is the error object, you can inspect and recover + * // event.originalEvent is the original event that failed to parse + * } + * } + * } + * ``` + * + * @param options Configure the parser with the `schema`, `envelope` and whether to `safeParse` or not + */ +export const parser = ( + options: ParserOptions +): HandlerMethodDecorator => { + return (_target, _propertyKey, descriptor) => { + const original = descriptor.value!; + + const { schema, envelope, safeParse } = options; + + descriptor.value = async function ( + this: Handler, + event: unknown, + context: Context, + callback + ) { + const parsedEvent: ParsedResult< + typeof event, + z.infer + > = parse(event, envelope, schema, safeParse); + + return original.call(this, parsedEvent, context, callback); + }; + + return descriptor; + }; +}; diff --git a/packages/parser/src/schemas/index.ts b/packages/parser/src/schemas/index.ts index 335846ad88..ff56350195 100644 --- a/packages/parser/src/schemas/index.ts +++ b/packages/parser/src/schemas/index.ts @@ -7,9 +7,9 @@ export { CloudFormationCustomResourceUpdateSchema, } from './cloudformation-custom-resource.js'; export { - CloudWatchLogsSchema, CloudWatchLogEventSchema, CloudWatchLogsDecodeSchema, + CloudWatchLogsSchema, } from './cloudwatch.js'; export { DynamoDBStreamSchema } from './dynamodb.js'; export { EventBridgeSchema } from './eventbridge.js'; @@ -21,13 +21,13 @@ export { } from './kinesis-firehose.js'; export { LambdaFunctionUrlSchema } from './lambda.js'; export { - S3Schema, - S3EventNotificationEventBridgeSchema, S3SqsEventNotificationSchema, + S3EventNotificationEventBridgeSchema, S3ObjectLambdaEventSchema, + S3Schema, } from './s3.js'; +export { SesSchema } from './ses.js'; export { SnsSchema } from './sns.js'; export { SqsSchema } from './sqs.js'; -export { SesSchema } from './ses.js'; export { VpcLatticeSchema } from './vpc-lattice.js'; export { VpcLatticeV2Schema } from './vpc-latticev2.js'; diff --git a/packages/parser/src/types/ParserOptions.ts b/packages/parser/src/types/ParserOptions.ts deleted file mode 100644 index efdf91cf95..0000000000 --- a/packages/parser/src/types/ParserOptions.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { ZodSchema } from 'zod'; -import { Envelope } from './envelope.js'; - -type ParserOptions = { - schema: S; - envelope?: Envelope; -}; - -export { type ParserOptions }; diff --git a/packages/parser/src/types/envelope.ts b/packages/parser/src/types/envelope.ts index c53f8893c8..9e049c1178 100644 --- a/packages/parser/src/types/envelope.ts +++ b/packages/parser/src/types/envelope.ts @@ -1,29 +1,32 @@ -import { type apiGatewayEnvelope } from '../envelopes/apigw.js'; -import { type apiGatewayV2Envelope } from '../envelopes/apigwv2.js'; -import { type cloudWatchEnvelope } from '../envelopes/cloudwatch.js'; -import { type dynamoDBStreamEnvelope } from '../envelopes/dynamodb.js'; -import { type kafkaEnvelope } from '../envelopes/kafka.js'; -import { type kinesisEnvelope } from '../envelopes/kinesis.js'; -import { type kinesisFirehoseEnvelope } from '../envelopes/kinesis-firehose.js'; -import { type lambdaFunctionUrlEnvelope } from '../envelopes/lambda.js'; -import { type snsEnvelope, type snsSqsEnvelope } from '../envelopes/sns.js'; -import { type sqsEnvelope } from '../envelopes/sqs.js'; -import { type vpcLatticeEnvelope } from '../envelopes/vpc-lattice.js'; -import { type vpcLatticeV2Envelope } from '../envelopes/vpc-latticev2.js'; -import { type eventBridgeEnvelope } from '../envelopes/event-bridge.js'; +import type { + ApiGatewayEnvelope, + KinesisFirehoseEnvelope, + KinesisEnvelope, + KafkaEnvelope, + CloudWatchEnvelope, + EventBridgeEnvelope, + ApiGatewayV2Envelope, + DynamoDBStreamEnvelope, + LambdaFunctionUrlEnvelope, + SnsEnvelope, + SnsSqsEnvelope, + SqsEnvelope, + VpcLatticeEnvelope, + VpcLatticeV2Envelope, +} from '../envelopes/index.js'; export type Envelope = - | typeof apiGatewayEnvelope - | typeof apiGatewayV2Envelope - | typeof cloudWatchEnvelope - | typeof dynamoDBStreamEnvelope - | typeof eventBridgeEnvelope - | typeof kafkaEnvelope - | typeof kinesisEnvelope - | typeof kinesisFirehoseEnvelope - | typeof lambdaFunctionUrlEnvelope - | typeof snsEnvelope - | typeof snsSqsEnvelope - | typeof sqsEnvelope - | typeof vpcLatticeEnvelope - | typeof vpcLatticeV2Envelope; + | typeof ApiGatewayEnvelope + | typeof ApiGatewayV2Envelope + | typeof CloudWatchEnvelope + | typeof DynamoDBStreamEnvelope + | typeof EventBridgeEnvelope + | typeof KafkaEnvelope + | typeof KinesisEnvelope + | typeof KinesisFirehoseEnvelope + | typeof LambdaFunctionUrlEnvelope + | typeof SnsEnvelope + | typeof SnsSqsEnvelope + | typeof SqsEnvelope + | typeof VpcLatticeEnvelope + | typeof VpcLatticeV2Envelope; diff --git a/packages/parser/src/types/index.ts b/packages/parser/src/types/index.ts index e69de29bb2..26052e60b6 100644 --- a/packages/parser/src/types/index.ts +++ b/packages/parser/src/types/index.ts @@ -0,0 +1,36 @@ +export type { + ParserOptions, + ParsedResult, + ParsedResultSuccess, + ParsedResultError, +} from '../types/parser.js'; +export type { Envelope } from './envelope.js'; + +export type { + ALBEvent, + APIGatewayProxyEvent, + ALBMultiValueHeadersEvent, + APIGatewayProxyEventV2, + S3Event, + S3EventNotificationEventBridge, + S3SqsEventNotification, + SnsEvent, + SqsEvent, + DynamoDBStreamEvent, + CloudWatchLogsEvent, + CloudFormationCustomResourceCreateEvent, + CloudFormationCustomResourceDeleteEvent, + CloudFormationCustomResourceUpdateEvent, + EventBridgeEvent, + KafkaSelfManagedEvent, + KafkaMskEvent, + KinesisDataStreamEvent, + KinesisDataStreamRecord, + KinesisDataStreamRecordPayload, + KinesisFireHoseEvent, + KinesisFireHoseSqsEvent, + LambdaFunctionUrlEvent, + SesEvent, + VpcLatticeEvent, + VpcLatticeEventV2, +} from './schema.js'; diff --git a/packages/parser/src/types/parser.ts b/packages/parser/src/types/parser.ts new file mode 100644 index 0000000000..c775a78d94 --- /dev/null +++ b/packages/parser/src/types/parser.ts @@ -0,0 +1,30 @@ +import type { ZodSchema, ZodError } from 'zod'; +import type { Envelope } from './envelope.js'; + +type ParserOptions = { + schema: S; + envelope?: Envelope; + safeParse?: boolean; +}; + +type ParsedResultSuccess = { + success: true; + data: Output; +}; + +type ParsedResultError = { + success: false; + error: ZodError | Error; + originalEvent: Input; +}; + +type ParsedResult = + | ParsedResultSuccess + | ParsedResultError; + +export type { + ParserOptions, + ParsedResult, + ParsedResultError, + ParsedResultSuccess, +}; diff --git a/packages/parser/src/types/schema.ts b/packages/parser/src/types/schema.ts index cc5869a1e2..6b18b57968 100644 --- a/packages/parser/src/types/schema.ts +++ b/packages/parser/src/types/schema.ts @@ -1,17 +1,120 @@ -import { KafkaRecordSchema } from '../schemas/kafka.js'; +import { + KafkaSelfManagedEventSchema, + KafkaMskEventSchema, +} from '../schemas/kafka.js'; import { z } from 'zod'; import { KinesisDataStreamRecord, KinesisDataStreamRecordPayload, + KinesisDataStreamSchema, } from '../schemas/kinesis.js'; import { APIGatewayProxyEventSchema } from '../schemas/apigw.js'; +import { AlbSchema, AlbMultiValueHeadersSchema } from '../schemas/alb.js'; +import { APIGatewayProxyEventV2Schema } from '../schemas/apigwv2.js'; +import { DynamoDBStreamSchema } from '../schemas/dynamodb.js'; +import { SqsSchema } from '../schemas/sqs.js'; +import { + CloudFormationCustomResourceCreateSchema, + CloudFormationCustomResourceDeleteSchema, + CloudFormationCustomResourceUpdateSchema, +} from '../schemas/cloudformation-custom-resource.js'; +import { CloudWatchLogsSchema } from '../schemas/cloudwatch.js'; +import { EventBridgeSchema } from '../schemas/eventbridge.js'; +import { + KinesisFirehoseSchema, + KinesisFirehoseSqsSchema, +} from '../schemas/kinesis-firehose.js'; +import { LambdaFunctionUrlSchema } from '../schemas/lambda.js'; +import { + S3EventNotificationEventBridgeSchema, + S3Schema, + S3SqsEventNotificationSchema, +} from '../schemas/s3.js'; +import { SesSchema } from '../schemas/ses.js'; +import { SnsSchema } from '../schemas/sns.js'; +import { VpcLatticeSchema } from '../schemas/vpc-lattice.js'; +import { VpcLatticeV2Schema } from '../schemas/vpc-latticev2.js'; -export type KafkaRecord = z.infer; +type ALBEvent = z.infer; -export type KinesisDataStreamRecord = z.infer; +type ALBMultiValueHeadersEvent = z.infer; -export type KinesisDataStreamRecordPayload = z.infer< - typeof KinesisDataStreamRecordPayload +type APIGatewayProxyEvent = z.infer; +type APIGatewayProxyEventV2 = z.infer; + +type CloudFormationCustomResourceCreateEvent = z.infer< + typeof CloudFormationCustomResourceCreateSchema +>; + +type CloudFormationCustomResourceDeleteEvent = z.infer< + typeof CloudFormationCustomResourceDeleteSchema >; -export type ApiGatewayProxyEvent = z.infer; +type CloudFormationCustomResourceUpdateEvent = z.infer< + typeof CloudFormationCustomResourceUpdateSchema +>; + +type CloudWatchLogsEvent = z.infer; + +type DynamoDBStreamEvent = z.infer; + +type EventBridgeEvent = z.infer; + +type KafkaSelfManagedEvent = z.infer; + +type KafkaMskEvent = z.infer; + +type KinesisDataStreamEvent = z.infer; + +type KinesisFireHoseEvent = z.infer; + +type KinesisFireHoseSqsEvent = z.infer; + +type LambdaFunctionUrlEvent = z.infer; + +type S3Event = z.infer; + +type S3EventNotificationEventBridge = z.infer< + typeof S3EventNotificationEventBridgeSchema +>; + +type S3SqsEventNotification = z.infer; + +type SesEvent = z.infer; + +type SnsEvent = z.infer; + +type SqsEvent = z.infer; + +type VpcLatticeEvent = z.infer; + +type VpcLatticeEventV2 = z.infer; + +export type { + ALBEvent, + ALBMultiValueHeadersEvent, + APIGatewayProxyEvent, + APIGatewayProxyEventV2, + CloudFormationCustomResourceCreateEvent, + CloudFormationCustomResourceDeleteEvent, + CloudFormationCustomResourceUpdateEvent, + CloudWatchLogsEvent, + DynamoDBStreamEvent, + EventBridgeEvent, + KafkaSelfManagedEvent, + KafkaMskEvent, + KinesisDataStreamEvent, + KinesisDataStreamRecord, + KinesisDataStreamRecordPayload, + KinesisFireHoseEvent, + KinesisFireHoseSqsEvent, + LambdaFunctionUrlEvent, + S3Event, + S3EventNotificationEventBridge, + S3SqsEventNotification, + SesEvent, + SnsEvent, + SqsEvent, + VpcLatticeEvent, + VpcLatticeEventV2, +}; diff --git a/packages/parser/tests/unit/envelope.test.ts b/packages/parser/tests/unit/envelope.test.ts new file mode 100644 index 0000000000..1f92ed6e64 --- /dev/null +++ b/packages/parser/tests/unit/envelope.test.ts @@ -0,0 +1,83 @@ +import { z, ZodError } from 'zod'; +import { Envelope } from '../../src/envelopes/envelope.js'; + +describe('envelope: ', () => { + describe('parseSafe', () => { + it('returns success response when input is object', () => { + const result = Envelope.safeParse( + '{"name": "John"}', + z.object({ name: z.string() }) + ); + expect(result).toEqual({ + success: true, + data: { name: 'John' }, + }); + }); + it('returns success response when input is string', () => { + const result = Envelope.safeParse( + { name: 'John' }, + z.object({ name: z.string() }) + ); + expect(result).toEqual({ + success: true, + data: { name: 'John' }, + }); + }); + it('returns error when input does not match schema', () => { + const result = Envelope.safeParse( + { name: 123 }, + z.object({ name: z.string() }) + ); + expect(result).toEqual({ + success: false, + error: expect.any(ZodError), + originalEvent: { name: 123 }, + }); + }); + + it('returns error when input is invalid JSON string', () => { + let err: unknown; + try { + JSON.parse('{name: "John"}'); + } catch (e) { + err = e; + } + const result = Envelope.safeParse( + '{name: "John"}', + z.object({ name: z.string() }) + ); + expect(result).toEqual({ + success: false, + error: err, + originalEvent: '{name: "John"}', + }); + }); + }); + + describe('parse', () => { + it('returns parsed data when input is object', () => { + const result = Envelope.parse( + { name: 'John' }, + z.object({ name: z.string() }) + ); + expect(result).toEqual({ name: 'John' }); + }); + it('returns parsed data when input is string', () => { + const result = Envelope.parse( + '{"name": "John"}', + z.object({ name: z.string() }) + ); + expect(result).toEqual({ name: 'John' }); + }); + it('throw custom error if input is not string or object', () => { + expect(() => Envelope.parse(123, z.object({ name: z.string() }))).toThrow( + 'Invalid data type for envelope. Expected string or object, got number' + ); + }); + it('throws error when input does not match schema', () => { + expect(() => + Envelope.parse({ name: 123 }, z.object({ name: z.string() })) + ).toThrow(); + }); + }); +}); diff --git a/packages/parser/tests/unit/envelopes/apigwt.test.ts b/packages/parser/tests/unit/envelopes/apigwt.test.ts index bed8445310..c9df0c03c7 100644 --- a/packages/parser/tests/unit/envelopes/apigwt.test.ts +++ b/packages/parser/tests/unit/envelopes/apigwt.test.ts @@ -6,24 +6,83 @@ import { generateMock } from '@anatine/zod-mock'; import { TestEvents, TestSchema } from '../schema/utils.js'; -import { ApiGatewayProxyEvent } from '../../../src/types/schema.js'; -import { apiGatewayEnvelope } from '../../../src/envelopes'; +import { APIGatewayProxyEvent } from '../../../src/types/'; +import { ApiGatewayEnvelope } from '../../../src/envelopes/index.js'; +import { ZodError } from 'zod'; describe('ApigwEnvelope ', () => { - it('should parse custom schema in envelope', () => { - const testCustomSchemaObject = generateMock(TestSchema); - const testEvent = TestEvents.apiGatewayProxyEvent as ApiGatewayProxyEvent; + describe('parse', () => { + it('should parse custom schema in envelope', () => { + const testCustomSchemaObject = generateMock(TestSchema); + const testEvent = TestEvents.apiGatewayProxyEvent as APIGatewayProxyEvent; - testEvent.body = JSON.stringify(testCustomSchemaObject); + testEvent.body = JSON.stringify(testCustomSchemaObject); - const resp = apiGatewayEnvelope(testEvent, TestSchema); - expect(resp).toEqual(testCustomSchemaObject); + const resp = ApiGatewayEnvelope.parse(testEvent, TestSchema); + expect(resp).toEqual(testCustomSchemaObject); + }); + + it('should throw no body provided', () => { + const testEvent = TestEvents.apiGatewayProxyEvent as APIGatewayProxyEvent; + testEvent.body = undefined; + + expect(() => ApiGatewayEnvelope.parse(testEvent, TestSchema)).toThrow(); + }); + it('should throw invalid event provided', () => { + const testEvent = TestEvents.apiGatewayProxyEvent as APIGatewayProxyEvent; + testEvent.body = 'invalid'; + + expect(() => ApiGatewayEnvelope.parse(testEvent, TestSchema)).toThrow(); + }); }); - it('should throw no body provided', () => { - const testEvent = TestEvents.apiGatewayProxyEvent as ApiGatewayProxyEvent; - testEvent.body = undefined; + describe('safeParse', () => { + it('should parse custom schema in envelope', () => { + const testCustomSchemaObject = generateMock(TestSchema); + const testEvent = TestEvents.apiGatewayProxyEvent as APIGatewayProxyEvent; + + testEvent.body = JSON.stringify(testCustomSchemaObject); + + const resp = ApiGatewayEnvelope.safeParse(testEvent, TestSchema); + expect(resp).toEqual({ + success: true, + data: testCustomSchemaObject, + }); + }); + + it('should return success false with original body if no body provided', () => { + const testEvent = TestEvents.apiGatewayProxyEvent as APIGatewayProxyEvent; + testEvent.body = undefined; + + const resp = ApiGatewayEnvelope.safeParse(testEvent, TestSchema); + expect(resp).toEqual({ + success: false, + error: expect.any(Error), + originalEvent: testEvent, + }); + }); + + it('should return success false with original body if invalid body provided', () => { + const testEvent = TestEvents.apiGatewayProxyEvent as APIGatewayProxyEvent; + testEvent.body = 'invalid'; - expect(() => apiGatewayEnvelope(testEvent, TestSchema)).toThrow(); + const resp = ApiGatewayEnvelope.safeParse(testEvent, TestSchema); + expect(resp).toEqual({ + success: false, + error: expect.any(SyntaxError), + originalEvent: testEvent, + }); + }); + it('should return success false if event is invalid', () => { + const resp = ApiGatewayEnvelope.safeParse( + 'invalid' as unknown, + TestSchema + ); + expect(resp).toEqual({ + success: false, + error: expect.any(ZodError), + originalEvent: 'invalid', + }); + }); }); }); diff --git a/packages/parser/tests/unit/envelopes/apigwv2.test.ts b/packages/parser/tests/unit/envelopes/apigwv2.test.ts index 5b2ec240fd..dd5a82609b 100644 --- a/packages/parser/tests/unit/envelopes/apigwv2.test.ts +++ b/packages/parser/tests/unit/envelopes/apigwv2.test.ts @@ -7,24 +7,88 @@ import { TestEvents, TestSchema } from '../schema/utils.js'; import { generateMock } from '@anatine/zod-mock'; import { APIGatewayProxyEventV2 } from 'aws-lambda'; -import { apiGatewayV2Envelope } from '../../../src/envelopes'; +import { ApiGatewayV2Envelope } from '../../../src/envelopes/index.js'; describe('ApiGwV2Envelope ', () => { - it('should parse custom schema in envelope', () => { - const testEvent = - TestEvents.apiGatewayProxyV2Event as APIGatewayProxyEventV2; - const data = generateMock(TestSchema); + describe('parse', () => { + it('should parse custom schema in envelope', () => { + const testEvent = + TestEvents.apiGatewayProxyV2Event as APIGatewayProxyEventV2; + const data = generateMock(TestSchema); - testEvent.body = JSON.stringify(data); + testEvent.body = JSON.stringify(data); - expect(apiGatewayV2Envelope(testEvent, TestSchema)).toEqual(data); + expect(ApiGatewayV2Envelope.parse(testEvent, TestSchema)).toEqual(data); + }); + + it('should throw when no body provided', () => { + const testEvent = + TestEvents.apiGatewayProxyV2Event as APIGatewayProxyEventV2; + testEvent.body = undefined; + + expect(() => ApiGatewayV2Envelope.parse(testEvent, TestSchema)).toThrow(); + }); + + it('should throw when invalid body provided', () => { + const testEvent = + TestEvents.apiGatewayProxyV2Event as APIGatewayProxyEventV2; + testEvent.body = 'invalid'; + + expect(() => ApiGatewayV2Envelope.parse(testEvent, TestSchema)).toThrow(); + }); + it('should throw when invalid event provided', () => { + expect(() => + ApiGatewayV2Envelope.parse({ foo: 'bar' }, TestSchema) + ).toThrow(); + }); }); - it('should throw when no body provided', () => { - const testEvent = - TestEvents.apiGatewayProxyV2Event as APIGatewayProxyEventV2; - testEvent.body = undefined; + describe('safeParse', () => { + it('should parse custom schema in envelope', () => { + const testEvent = + TestEvents.apiGatewayProxyV2Event as APIGatewayProxyEventV2; + const data = generateMock(TestSchema); + + testEvent.body = JSON.stringify(data); + + expect(ApiGatewayV2Envelope.safeParse(testEvent, TestSchema)).toEqual({ + success: true, + data, + }); + }); + + it('should return success false with original body if no body provided', () => { + const testEvent = + TestEvents.apiGatewayProxyV2Event as APIGatewayProxyEventV2; + testEvent.body = undefined; + + expect(ApiGatewayV2Envelope.safeParse(testEvent, TestSchema)).toEqual({ + success: false, + error: expect.any(Error), + originalEvent: testEvent, + }); + }); + + it('should return success false with original body if invalid body provided', () => { + const testEvent = + TestEvents.apiGatewayProxyV2Event as APIGatewayProxyEventV2; + testEvent.body = 'invalid'; + + expect(ApiGatewayV2Envelope.safeParse(testEvent, TestSchema)).toEqual({ + success: false, + error: expect.any(Error), + originalEvent: testEvent, + }); + }); - expect(() => apiGatewayV2Envelope(testEvent, TestSchema)).toThrow(); + it('should return success false with original event if invalid event provided', () => { + expect( + ApiGatewayV2Envelope.safeParse({ foo: 'bar' }, TestSchema) + ).toEqual({ + success: false, + error: expect.any(Error), + originalEvent: { foo: 'bar' }, + }); + }); }); }); diff --git a/packages/parser/tests/unit/envelopes/cloudwatch.test.ts b/packages/parser/tests/unit/envelopes/cloudwatch.test.ts index 4c238bac48..adfe6e52f9 100644 --- a/packages/parser/tests/unit/envelopes/cloudwatch.test.ts +++ b/packages/parser/tests/unit/envelopes/cloudwatch.test.ts @@ -9,55 +9,123 @@ import { gzipSync } from 'node:zlib'; import { CloudWatchLogEventSchema, CloudWatchLogsDecodeSchema, -} from '../../../src/schemas'; +} from '../../../src/schemas/'; import { TestSchema } from '../schema/utils.js'; -import { cloudWatchEnvelope } from '../../../src/envelopes'; +import { CloudWatchEnvelope } from '../../../src/envelopes/index.js'; +import { ZodError } from 'zod'; describe('CloudWatch', () => { - it('should parse custom schema in envelope', () => { - const testEvent = { - awslogs: { - data: '', - }, - }; - - const data = generateMock(TestSchema); - const eventMock = generateMock(CloudWatchLogEventSchema, { - stringMap: { - message: () => JSON.stringify(data), - }, + describe('parse', () => { + it('should parse custom schema in envelope', () => { + const testEvent = { + awslogs: { + data: '', + }, + }; + + const data = generateMock(TestSchema); + const eventMock = generateMock(CloudWatchLogEventSchema, { + stringMap: { + message: () => JSON.stringify(data), + }, + }); + + const logMock = generateMock(CloudWatchLogsDecodeSchema); + logMock.logEvents = [eventMock]; + + testEvent.awslogs.data = gzipSync( + Buffer.from(JSON.stringify(logMock), 'utf8') + ).toString('base64'); + + expect(CloudWatchEnvelope.parse(testEvent, TestSchema)).toEqual([data]); }); - const logMock = generateMock(CloudWatchLogsDecodeSchema); - logMock.logEvents = [eventMock]; + it('should throw when schema does not match', () => { + const testEvent = { + awslogs: { + data: '', + }, + }; - testEvent.awslogs.data = gzipSync( - Buffer.from(JSON.stringify(logMock), 'utf8') - ).toString('base64'); + const eventMock = generateMock(CloudWatchLogEventSchema, { + stringMap: { + message: () => JSON.stringify({ foo: 'bar' }), + }, + }); - expect(cloudWatchEnvelope(testEvent, TestSchema)).toEqual([data]); + const logMock = generateMock(CloudWatchLogsDecodeSchema); + logMock.logEvents = [eventMock]; + + testEvent.awslogs.data = gzipSync( + Buffer.from(JSON.stringify(logMock), 'utf8') + ).toString('base64'); + + expect(() => CloudWatchEnvelope.parse(testEvent, TestSchema)).toThrow(); + }); }); - it('should throw when schema does not match', () => { - const testEvent = { - awslogs: { - data: '', - }, - }; - - const eventMock = generateMock(CloudWatchLogEventSchema, { - stringMap: { - message: () => JSON.stringify({ foo: 'bar' }), - }, + describe('safeParse', () => { + it('should parse custom schema in envelope', () => { + const testEvent = { + awslogs: { + data: '', + }, + }; + + const data = generateMock(TestSchema); + const eventMock = generateMock(CloudWatchLogEventSchema, { + stringMap: { + message: () => JSON.stringify(data), + }, + }); + + const logMock = generateMock(CloudWatchLogsDecodeSchema); + logMock.logEvents = [eventMock]; + + testEvent.awslogs.data = gzipSync( + Buffer.from(JSON.stringify(logMock), 'utf8') + ).toString('base64'); + + const actual = CloudWatchEnvelope.safeParse(testEvent, TestSchema); + expect(actual).toEqual({ + success: true, + data: [data], + }); }); - const logMock = generateMock(CloudWatchLogsDecodeSchema); - logMock.logEvents = [eventMock]; + it('should return success false when schema does not match', () => { + const testEvent = { + awslogs: { + data: '', + }, + }; + + const eventMock = generateMock(CloudWatchLogEventSchema, { + stringMap: { + message: () => JSON.stringify({ foo: 'bar' }), + }, + }); - testEvent.awslogs.data = gzipSync( - Buffer.from(JSON.stringify(logMock), 'utf8') - ).toString('base64'); + const logMock = generateMock(CloudWatchLogsDecodeSchema); + logMock.logEvents = [eventMock]; - expect(() => cloudWatchEnvelope(testEvent, TestSchema)).toThrow(); + testEvent.awslogs.data = gzipSync( + Buffer.from(JSON.stringify(logMock), 'utf8') + ).toString('base64'); + + expect(CloudWatchEnvelope.safeParse(testEvent, TestSchema)).toEqual({ + success: false, + error: expect.any(Error), + originalEvent: testEvent, + }); + }); + + it('should return success false when envelope does not match', () => { + expect(CloudWatchEnvelope.safeParse({ foo: 'bar' }, TestSchema)).toEqual({ + success: false, + error: expect.any(ZodError), + originalEvent: { foo: 'bar' }, + }); + }); }); }); diff --git a/packages/parser/tests/unit/envelopes/dynamodb.test.ts b/packages/parser/tests/unit/envelopes/dynamodb.test.ts index 01814153a1..4d2c9fb657 100644 --- a/packages/parser/tests/unit/envelopes/dynamodb.test.ts +++ b/packages/parser/tests/unit/envelopes/dynamodb.test.ts @@ -7,37 +7,122 @@ import { generateMock } from '@anatine/zod-mock'; import { TestEvents } from '../schema/utils.js'; import { DynamoDBStreamEvent } from 'aws-lambda'; -import { z } from 'zod'; -import { dynamoDBStreamEnvelope } from '../../../src/envelopes'; +import { z, ZodError } from 'zod'; +import { DynamoDBStreamEnvelope } from '../../../src/envelopes/index.js'; describe('DynamoDB', () => { const schema = z.object({ Message: z.record(z.literal('S'), z.string()), Id: z.record(z.literal('N'), z.number().min(0).max(100)), }); + const mockOldImage = generateMock(schema); + const mockNewImage = generateMock(schema); + const dynamodbEvent = TestEvents.dynamoStreamEvent as DynamoDBStreamEvent; + (dynamodbEvent.Records[0].dynamodb!.NewImage as typeof mockNewImage) = + mockNewImage; + (dynamodbEvent.Records[1].dynamodb!.NewImage as typeof mockNewImage) = + mockNewImage; + (dynamodbEvent.Records[0].dynamodb!.OldImage as typeof mockOldImage) = + mockOldImage; + (dynamodbEvent.Records[1].dynamodb!.OldImage as typeof mockOldImage) = + mockOldImage; + describe('parse', () => { + it('parse should parse dynamodb envelope', () => { + const parsed = DynamoDBStreamEnvelope.parse(dynamodbEvent, schema); + expect(parsed[0]).toEqual({ + OldImage: mockOldImage, + NewImage: mockNewImage, + }); + expect(parsed[1]).toEqual({ + OldImage: mockOldImage, + NewImage: mockNewImage, + }); + }); + it('parse should throw error if envelope invalid', () => { + expect(() => + DynamoDBStreamEnvelope.parse({ foo: 'bar' }, schema) + ).toThrow(); + }); + it('parse should throw error if new or old image is invalid', () => { + const ddbEvent = TestEvents.dynamoStreamEvent as DynamoDBStreamEvent; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + ddbEvent.Records[0].dynamodb!.NewImage.Id = 'foo'; + expect(() => DynamoDBStreamEnvelope.parse(ddbEvent, schema)).toThrow(); + }); + }); + + describe('safeParse', () => { + it('safeParse should parse dynamodb envelope', () => { + const parsed = DynamoDBStreamEnvelope.safeParse(dynamodbEvent, schema); + expect(parsed.success).toBe(true); + expect(parsed).toEqual({ + success: true, + data: [ + { + OldImage: mockOldImage, + NewImage: mockNewImage, + }, + { + OldImage: mockOldImage, + NewImage: mockNewImage, + }, + ], + }); + }); + it('safeParse should return error if NewImage is invalid', () => { + const invalidDDBEvent = + TestEvents.dynamoStreamEvent as DynamoDBStreamEvent; - it('should parse dynamodb envelope', () => { - const mockOldImage = generateMock(schema); - const mockNewImage = generateMock(schema); - const dynamodbEvent = TestEvents.dynamoStreamEvent as DynamoDBStreamEvent; - - (dynamodbEvent.Records[0].dynamodb!.NewImage as typeof mockNewImage) = - mockNewImage; - (dynamodbEvent.Records[1].dynamodb!.NewImage as typeof mockNewImage) = - mockNewImage; - (dynamodbEvent.Records[0].dynamodb!.OldImage as typeof mockOldImage) = - mockOldImage; - (dynamodbEvent.Records[1].dynamodb!.OldImage as typeof mockOldImage) = - mockOldImage; - - const parsed = dynamoDBStreamEnvelope(dynamodbEvent, schema); - expect(parsed[0]).toEqual({ - OldImage: mockOldImage, - NewImage: mockNewImage, + (invalidDDBEvent.Records[0].dynamodb!.NewImage as typeof mockNewImage) = { + Id: { N: 101 }, + Message: { S: 'foo' }, + }; + (invalidDDBEvent.Records[1].dynamodb!.NewImage as typeof mockNewImage) = + mockNewImage; + (invalidDDBEvent.Records[0].dynamodb!.OldImage as typeof mockOldImage) = + mockOldImage; + (invalidDDBEvent.Records[1].dynamodb!.OldImage as typeof mockOldImage) = + mockOldImage; + + const parsed = DynamoDBStreamEnvelope.safeParse(invalidDDBEvent, schema); + expect(parsed).toEqual({ + success: false, + error: expect.any(ZodError), + originalEvent: invalidDDBEvent, + }); + }); + + it('safeParse should return error if OldImage is invalid', () => { + const invalidDDBEvent = + TestEvents.dynamoStreamEvent as DynamoDBStreamEvent; + + (invalidDDBEvent.Records[0].dynamodb!.OldImage as typeof mockNewImage) = { + Id: { N: 101 }, + Message: { S: 'foo' }, + }; + (invalidDDBEvent.Records[1].dynamodb!.NewImage as typeof mockNewImage) = + mockNewImage; + (invalidDDBEvent.Records[0].dynamodb!.OldImage as typeof mockOldImage) = + mockOldImage; + (invalidDDBEvent.Records[0].dynamodb!.NewImage as typeof mockNewImage) = + mockNewImage; + + const parsed = DynamoDBStreamEnvelope.safeParse(invalidDDBEvent, schema); + expect(parsed).toEqual({ + success: false, + error: expect.any(ZodError), + originalEvent: invalidDDBEvent, + }); }); - expect(parsed[1]).toEqual({ - OldImage: mockOldImage, - NewImage: mockNewImage, + + it('safeParse should return error if envelope is invalid', () => { + const parsed = DynamoDBStreamEnvelope.safeParse({ foo: 'bar' }, schema); + expect(parsed).toEqual({ + success: false, + error: expect.any(ZodError), + originalEvent: { foo: 'bar' }, + }); }); }); }); diff --git a/packages/parser/tests/unit/envelopes/eventbridge.test.ts b/packages/parser/tests/unit/envelopes/eventbridge.test.ts index 5f5281caa5..746d95b160 100644 --- a/packages/parser/tests/unit/envelopes/eventbridge.test.ts +++ b/packages/parser/tests/unit/envelopes/eventbridge.test.ts @@ -7,45 +7,116 @@ import { TestEvents, TestSchema } from '../schema/utils.js'; import { generateMock } from '@anatine/zod-mock'; import { EventBridgeEvent } from 'aws-lambda'; -import { eventBridgeEnvelope } from '../../../src/envelopes'; +import { ZodError } from 'zod'; +import { EventBridgeEnvelope } from '../../../src/envelopes/index.js'; describe('EventBridgeEnvelope ', () => { - it('should parse eventbridge event', () => { - const eventBridgeEvent = TestEvents.eventBridgeEvent as EventBridgeEvent< - string, - object - >; + describe('parse', () => { + it('should parse eventbridge event', () => { + const eventBridgeEvent = TestEvents.eventBridgeEvent as EventBridgeEvent< + string, + object + >; - const data = generateMock(TestSchema); + const data = generateMock(TestSchema); - eventBridgeEvent.detail = data; + eventBridgeEvent.detail = data; - expect(eventBridgeEnvelope(eventBridgeEvent, TestSchema)).toEqual(data); - }); + expect(EventBridgeEnvelope.parse(eventBridgeEvent, TestSchema)).toEqual( + data + ); + }); + + it('should throw error if detail type does not match schema', () => { + const eventBridgeEvent = TestEvents.eventBridgeEvent as EventBridgeEvent< + string, + object + >; + + eventBridgeEvent.detail = { + foo: 'bar', + }; - it('should throw error if detail type does not match schema', () => { - const eventBridgeEvent = TestEvents.eventBridgeEvent as EventBridgeEvent< - string, - object - >; + expect(() => + EventBridgeEnvelope.parse(eventBridgeEvent, TestSchema) + ).toThrowError(); + }); - eventBridgeEvent.detail = { - foo: 'bar', - }; + it('should throw when invalid data type provided', () => { + const eventBridgeEvent = TestEvents.eventBridgeEvent as EventBridgeEvent< + string, + object + >; - expect(() => - eventBridgeEnvelope(eventBridgeEvent, TestSchema) - ).toThrowError(); + eventBridgeEvent.detail = 1 as unknown as object; + + expect(() => + EventBridgeEnvelope.parse(eventBridgeEvent, TestSchema) + ).toThrow(); + }); }); - it('should throw when invalid data type provided', () => { - const eventBridgeEvent = TestEvents.eventBridgeEvent as EventBridgeEvent< - string, - object - >; + describe('safeParse', () => { + it('should safe parse eventbridge event', () => { + const eventBridgeEvent = TestEvents.eventBridgeEvent as EventBridgeEvent< + string, + object + >; + + const data = generateMock(TestSchema); + + eventBridgeEvent.detail = data; + + expect( + EventBridgeEnvelope.safeParse(eventBridgeEvent, TestSchema) + ).toEqual({ + success: true, + data: data, + }); + }); + + it('should safe parse eventbridge event and return original event if invalid', () => { + const eventBridgeEvent = TestEvents.eventBridgeEvent as EventBridgeEvent< + string, + object + >; + + eventBridgeEvent.detail = { + foo: 'bar', + }; + + expect( + EventBridgeEnvelope.safeParse(eventBridgeEvent, TestSchema) + ).toEqual({ + success: false, + error: expect.any(ZodError), + originalEvent: eventBridgeEvent, + }); + }); + + it('should safe parse eventbridge event and return original event if invalid data type', () => { + const eventBridgeEvent = TestEvents.eventBridgeEvent as EventBridgeEvent< + string, + object + >; + + eventBridgeEvent.detail = 1 as unknown as object; - eventBridgeEvent.detail = 1 as unknown as object; + expect( + EventBridgeEnvelope.safeParse(eventBridgeEvent, TestSchema) + ).toEqual({ + success: false, + error: expect.any(Error), + originalEvent: eventBridgeEvent, + }); + }); - expect(() => eventBridgeEnvelope(eventBridgeEvent, TestSchema)).toThrow(); + it('should return original event and error envelope is invalid', () => { + expect(EventBridgeEnvelope.safeParse(1, TestSchema)).toEqual({ + success: false, + error: expect.any(ZodError), + originalEvent: 1, + }); + }); }); }); diff --git a/packages/parser/tests/unit/envelopes/kafka.test.ts b/packages/parser/tests/unit/envelopes/kafka.test.ts index 509c333b4c..5c55013244 100644 --- a/packages/parser/tests/unit/envelopes/kafka.test.ts +++ b/packages/parser/tests/unit/envelopes/kafka.test.ts @@ -7,33 +7,90 @@ import { generateMock } from '@anatine/zod-mock'; import { TestEvents, TestSchema } from '../schema/utils.js'; import { MSKEvent, SelfManagedKafkaEvent } from 'aws-lambda'; -import { kafkaEnvelope } from '../../../src/envelopes'; +import { KafkaEnvelope } from '../../../src/envelopes/index.js'; describe('Kafka', () => { - it('should parse MSK kafka envelope', () => { - const mock = generateMock(TestSchema); + describe('parse', () => { + it('should parse MSK kafka envelope', () => { + const mock = generateMock(TestSchema); - const kafkaEvent = TestEvents.kafkaEventMsk as MSKEvent; - kafkaEvent.records['mytopic-0'][0].value = Buffer.from( - JSON.stringify(mock) - ).toString('base64'); + const kafkaEvent = TestEvents.kafkaEventMsk as MSKEvent; + kafkaEvent.records['mytopic-0'][0].value = Buffer.from( + JSON.stringify(mock) + ).toString('base64'); - const result = kafkaEnvelope(kafkaEvent, TestSchema); + const result = KafkaEnvelope.parse(kafkaEvent, TestSchema); - expect(result).toEqual([[mock]]); - }); + expect(result).toEqual([[mock]]); + }); + + it('should parse Self Managed kafka envelope', () => { + const mock = generateMock(TestSchema); + + const kafkaEvent = + TestEvents.kafkaEventSelfManaged as SelfManagedKafkaEvent; + kafkaEvent.records['mytopic-0'][0].value = Buffer.from( + JSON.stringify(mock) + ).toString('base64'); + + const result = KafkaEnvelope.parse(kafkaEvent, TestSchema); + + expect(result).toEqual([[mock]]); + }); + + describe('safeParse', () => { + it('should parse MSK kafka envelope', () => { + const mock = generateMock(TestSchema); + + const kafkaEvent = TestEvents.kafkaEventMsk as MSKEvent; + kafkaEvent.records['mytopic-0'][0].value = Buffer.from( + JSON.stringify(mock) + ).toString('base64'); + + const result = KafkaEnvelope.safeParse(kafkaEvent, TestSchema); + + expect(result).toEqual({ + success: true, + data: [mock], + }); + }); + + it('should parse Self Managed kafka envelope', () => { + const mock = generateMock(TestSchema); + + const kafkaEvent = + TestEvents.kafkaEventSelfManaged as SelfManagedKafkaEvent; + kafkaEvent.records['mytopic-0'][0].value = Buffer.from( + JSON.stringify(mock) + ).toString('base64'); + + const result = KafkaEnvelope.safeParse(kafkaEvent, TestSchema); - it('should parse Self Managed kafka envelope', () => { - const mock = generateMock(TestSchema); + expect(result).toEqual({ + success: true, + data: [mock], + }); + }); - const kafkaEvent = - TestEvents.kafkaEventSelfManaged as SelfManagedKafkaEvent; - kafkaEvent.records['mytopic-0'][0].value = Buffer.from( - JSON.stringify(mock) - ).toString('base64'); + it('should return original event on failure', () => { + const kafkaEvent = TestEvents.kafkaEventMsk as MSKEvent; + kafkaEvent.records['mytopic-0'][0].value = 'not a valid json'; - const result = kafkaEnvelope(kafkaEvent, TestSchema); + const result = KafkaEnvelope.safeParse(kafkaEvent, TestSchema); - expect(result).toEqual([[mock]]); + expect(result).toEqual({ + success: false, + error: expect.any(Error), + originalEvent: kafkaEvent, + }); + }); + it('should return original event and error if envelope is invalid', () => { + expect(KafkaEnvelope.safeParse({ foo: 'bar' }, TestSchema)).toEqual({ + success: false, + error: expect.any(Error), + originalEvent: { foo: 'bar' }, + }); + }); + }); }); }); diff --git a/packages/parser/tests/unit/envelopes/kinesis-firehose.test.ts b/packages/parser/tests/unit/envelopes/kinesis-firehose.test.ts index 7983fd3ae3..50951d7c0c 100644 --- a/packages/parser/tests/unit/envelopes/kinesis-firehose.test.ts +++ b/packages/parser/tests/unit/envelopes/kinesis-firehose.test.ts @@ -6,50 +6,159 @@ import { TestEvents, TestSchema } from '../schema/utils.js'; import { generateMock } from '@anatine/zod-mock'; -import { KinesisFirehoseSchema } from '../../../src/schemas'; +import { KinesisFirehoseSchema } from '../../../src/schemas/'; import { z } from 'zod'; -import { kinesisFirehoseEnvelope } from '../../../src/envelopes'; +import { KinesisFirehoseEnvelope } from '../../../src/envelopes/index.js'; describe('Kinesis Firehose Envelope', () => { - it('should parse records for PutEvent', () => { - const mock = generateMock(TestSchema); - const testEvent = TestEvents.kinesisFirehosePutEvent as z.infer< - typeof KinesisFirehoseSchema - >; + describe('parse', () => { + it('should parse records for PutEvent', () => { + const mock = generateMock(TestSchema); + const testEvent = TestEvents.kinesisFirehosePutEvent as z.infer< + typeof KinesisFirehoseSchema + >; - testEvent.records.map((record) => { - record.data = Buffer.from(JSON.stringify(mock)).toString('base64'); + testEvent.records.map((record) => { + record.data = Buffer.from(JSON.stringify(mock)).toString('base64'); + }); + + const resp = KinesisFirehoseEnvelope.parse(testEvent, TestSchema); + expect(resp).toEqual([mock, mock]); }); - const resp = kinesisFirehoseEnvelope(testEvent, TestSchema); - expect(resp).toEqual([mock, mock]); - }); + it('should parse a single record for SQS event', () => { + const mock = generateMock(TestSchema); + const testEvent = TestEvents.kinesisFirehoseSQSEvent as z.infer< + typeof KinesisFirehoseSchema + >; + + testEvent.records.map((record) => { + record.data = Buffer.from(JSON.stringify(mock)).toString('base64'); + }); + + const resp = KinesisFirehoseEnvelope.parse(testEvent, TestSchema); + expect(resp).toEqual([mock]); + }); + + it('should parse records for kinesis event', () => { + const mock = generateMock(TestSchema); + const testEvent = TestEvents.kinesisFirehoseKinesisEvent as z.infer< + typeof KinesisFirehoseSchema + >; - it('should parse a single record for SQS event', () => { - const mock = generateMock(TestSchema); - const testEvent = TestEvents.kinesisFirehoseSQSEvent as z.infer< - typeof KinesisFirehoseSchema - >; + testEvent.records.map((record) => { + record.data = Buffer.from(JSON.stringify(mock)).toString('base64'); + }); - testEvent.records.map((record) => { - record.data = Buffer.from(JSON.stringify(mock)).toString('base64'); + const resp = KinesisFirehoseEnvelope.parse(testEvent, TestSchema); + expect(resp).toEqual([mock, mock]); }); + it('should throw if record is not base64 encoded', () => { + const testEvent = TestEvents.kinesisFirehosePutEvent as z.infer< + typeof KinesisFirehoseSchema + >; - const resp = kinesisFirehoseEnvelope(testEvent, TestSchema); - expect(resp).toEqual([mock]); + testEvent.records.map((record) => { + record.data = 'not base64 encoded'; + }); + + expect(() => { + KinesisFirehoseEnvelope.parse(testEvent, TestSchema); + }).toThrow(); + }); + it('should throw if envelope is invalid', () => { + expect(() => { + KinesisFirehoseEnvelope.parse({ foo: 'bar' }, TestSchema); + }).toThrow(); + }); + it('should throw when schema does not match record', () => { + const testEvent = TestEvents.kinesisFirehosePutEvent as z.infer< + typeof KinesisFirehoseSchema + >; + + testEvent.records.map((record) => { + record.data = Buffer.from('not a valid json').toString('base64'); + }); + + expect(() => { + KinesisFirehoseEnvelope.parse(testEvent, TestSchema); + }).toThrow(); + }); }); + describe('safeParse', () => { + it('should parse records for PutEvent', () => { + const mock = generateMock(TestSchema); + const testEvent = TestEvents.kinesisFirehosePutEvent as z.infer< + typeof KinesisFirehoseSchema + >; - it('should parse records for kinesis event', () => { - const mock = generateMock(TestSchema); - const testEvent = TestEvents.kinesisFirehoseKinesisEvent as z.infer< - typeof KinesisFirehoseSchema - >; + testEvent.records.map((record) => { + record.data = Buffer.from(JSON.stringify(mock)).toString('base64'); + }); - testEvent.records.map((record) => { - record.data = Buffer.from(JSON.stringify(mock)).toString('base64'); + const resp = KinesisFirehoseEnvelope.safeParse(testEvent, TestSchema); + expect(resp).toEqual({ success: true, data: [mock, mock] }); }); - const resp = kinesisFirehoseEnvelope(testEvent, TestSchema); - expect(resp).toEqual([mock, mock]); + it('should parse a single record for SQS event', () => { + const mock = generateMock(TestSchema); + const testEvent = TestEvents.kinesisFirehoseSQSEvent as z.infer< + typeof KinesisFirehoseSchema + >; + + testEvent.records.map((record) => { + record.data = Buffer.from(JSON.stringify(mock)).toString('base64'); + }); + + const resp = KinesisFirehoseEnvelope.safeParse(testEvent, TestSchema); + expect(resp).toEqual({ success: true, data: [mock] }); + }); + + it('should parse records for kinesis event', () => { + const mock = generateMock(TestSchema); + const testEvent = TestEvents.kinesisFirehoseKinesisEvent as z.infer< + typeof KinesisFirehoseSchema + >; + + testEvent.records.map((record) => { + record.data = Buffer.from(JSON.stringify(mock)).toString('base64'); + }); + + const resp = KinesisFirehoseEnvelope.safeParse(testEvent, TestSchema); + expect(resp).toEqual({ success: true, data: [mock, mock] }); + }); + it('should return original event if envelope is invalid', () => { + expect( + KinesisFirehoseEnvelope.safeParse({ foo: 'bar' }, TestSchema) + ).toEqual({ + success: false, + error: expect.any(Error), + originalEvent: { foo: 'bar' }, + }); + }); + it('should return original event if record is not base64 encoded', () => { + const testEvent = TestEvents.kinesisFirehosePutEvent as z.infer< + typeof KinesisFirehoseSchema + >; + + testEvent.records.map((record) => { + record.data = 'not base64 encoded'; + }); + + expect(KinesisFirehoseEnvelope.safeParse(testEvent, TestSchema)).toEqual({ + success: false, + error: expect.any(Error), + originalEvent: testEvent, + }); + }); + it('should return original event envelope is invalid', () => { + expect( + KinesisFirehoseEnvelope.safeParse({ foo: 'bar' }, TestSchema) + ).toEqual({ + success: false, + error: expect.any(Error), + originalEvent: { foo: 'bar' }, + }); + }); }); }); diff --git a/packages/parser/tests/unit/envelopes/kinesis.test.ts b/packages/parser/tests/unit/envelopes/kinesis.test.ts index ed116e24a3..f84149c252 100644 --- a/packages/parser/tests/unit/envelopes/kinesis.test.ts +++ b/packages/parser/tests/unit/envelopes/kinesis.test.ts @@ -7,20 +7,66 @@ import { generateMock } from '@anatine/zod-mock'; import { KinesisStreamEvent } from 'aws-lambda'; import { TestEvents, TestSchema } from '../schema/utils.js'; -import { kinesisEnvelope } from '../../../src/envelopes'; +import { KinesisEnvelope } from '../../../src/envelopes/index.js'; +import { ZodError } from 'zod'; -describe('Kinesis', () => { - it('should parse Kinesis Stream event', () => { - const mock = generateMock(TestSchema); - const testEvent = TestEvents.kinesisStreamEvent as KinesisStreamEvent; +describe('KinesisEnvelope', () => { + describe('parse', () => { + it('should parse Kinesis Stream event', () => { + const mock = generateMock(TestSchema); + const testEvent = TestEvents.kinesisStreamEvent as KinesisStreamEvent; - testEvent.Records.map((record) => { - record.kinesis.data = Buffer.from(JSON.stringify(mock)).toString( - 'base64' - ); + testEvent.Records.map((record) => { + record.kinesis.data = Buffer.from(JSON.stringify(mock)).toString( + 'base64' + ); + }); + + const resp = KinesisEnvelope.parse(testEvent, TestSchema); + expect(resp).toEqual([mock, mock]); + }); + it('should throw if envelope is invalid', () => { + expect(() => KinesisEnvelope.parse({ foo: 'bar' }, TestSchema)).toThrow(); + }); + it('should throw if record is invalid', () => { + const testEvent = TestEvents.kinesisStreamEvent as KinesisStreamEvent; + testEvent.Records[0].kinesis.data = 'invalid'; + expect(() => KinesisEnvelope.parse(testEvent, TestSchema)).toThrow(); }); + }); + + describe('safeParse', () => { + it('should parse Kinesis Stream event', () => { + const mock = generateMock(TestSchema); + const testEvent = TestEvents.kinesisStreamEvent as KinesisStreamEvent; - const resp = kinesisEnvelope(testEvent, TestSchema); - expect(resp).toEqual([mock, mock]); + testEvent.Records.map((record) => { + record.kinesis.data = Buffer.from(JSON.stringify(mock)).toString( + 'base64' + ); + }); + + const resp = KinesisEnvelope.safeParse(testEvent, TestSchema); + expect(resp).toEqual({ success: true, data: [mock, mock] }); + }); + it('should return original event if envelope is invalid', () => { + const testEvent = { foo: 'bar' }; + const resp = KinesisEnvelope.safeParse(testEvent, TestSchema); + expect(resp).toEqual({ + success: false, + error: expect.any(ZodError), + originalEvent: testEvent, + }); + }); + it('should return original event if record is invalid', () => { + const testEvent = TestEvents.kinesisStreamEvent as KinesisStreamEvent; + testEvent.Records[0].kinesis.data = 'invalid'; + const resp = KinesisEnvelope.safeParse(testEvent, TestSchema); + expect(resp).toEqual({ + success: false, + error: expect.any(SyntaxError), + originalEvent: testEvent, + }); + }); }); }); diff --git a/packages/parser/tests/unit/envelopes/lambda.test.ts b/packages/parser/tests/unit/envelopes/lambda.test.ts index b31697cf08..56b0551cfd 100644 --- a/packages/parser/tests/unit/envelopes/lambda.test.ts +++ b/packages/parser/tests/unit/envelopes/lambda.test.ts @@ -1,30 +1,92 @@ +import { LambdaFunctionUrlEnvelope } from '../../../src/envelopes/index.js'; +import { TestEvents, TestSchema } from '../schema/utils.js'; +import { generateMock } from '@anatine/zod-mock'; +import { APIGatewayProxyEventV2 } from 'aws-lambda'; + /** * Test built in schema envelopes for Lambda Functions URL * * @group unit/parser/envelopes */ -import { TestEvents, TestSchema } from '../schema/utils.js'; -import { generateMock } from '@anatine/zod-mock'; -import { APIGatewayProxyEventV2 } from 'aws-lambda'; -import { lambdaFunctionUrlEnvelope } from '../../../src/envelopes'; - describe('Lambda Functions Url ', () => { - it('should parse custom schema in envelope', () => { - const testEvent = - TestEvents.lambdaFunctionUrlEvent as APIGatewayProxyEventV2; - const data = generateMock(TestSchema); + describe('parse', () => { + it('should parse custom schema in envelope', () => { + const testEvent = + TestEvents.lambdaFunctionUrlEvent as APIGatewayProxyEventV2; + const data = generateMock(TestSchema); - testEvent.body = JSON.stringify(data); + testEvent.body = JSON.stringify(data); - expect(lambdaFunctionUrlEnvelope(testEvent, TestSchema)).toEqual(data); + expect(LambdaFunctionUrlEnvelope.parse(testEvent, TestSchema)).toEqual( + data + ); + }); + + it('should throw when no body provided', () => { + const testEvent = + TestEvents.apiGatewayProxyV2Event as APIGatewayProxyEventV2; + testEvent.body = undefined; + + expect(() => + LambdaFunctionUrlEnvelope.parse(testEvent, TestSchema) + ).toThrow(); + }); + + it('should throw when envelope is not valid', () => { + expect(() => + LambdaFunctionUrlEnvelope.parse({ foo: 'bar' }, TestSchema) + ).toThrow(); + }); + + it('should throw when body does not match schema', () => { + const testEvent = + TestEvents.lambdaFunctionUrlEvent as APIGatewayProxyEventV2; + testEvent.body = JSON.stringify({ foo: 'bar' }); + + expect(() => + LambdaFunctionUrlEnvelope.parse(testEvent, TestSchema) + ).toThrow(); + }); }); + describe('safeParse', () => { + it('should parse custom schema in envelope', () => { + const testEvent = + TestEvents.lambdaFunctionUrlEvent as APIGatewayProxyEventV2; + const data = generateMock(TestSchema); + + testEvent.body = JSON.stringify(data); + + expect( + LambdaFunctionUrlEnvelope.safeParse(testEvent, TestSchema) + ).toEqual({ + success: true, + data, + }); + }); + + it('should return original event when envelope is not valid', () => { + expect( + LambdaFunctionUrlEnvelope.safeParse({ foo: 'bar' }, TestSchema) + ).toEqual({ + success: false, + error: expect.any(Error), + originalEvent: { foo: 'bar' }, + }); + }); - it('should throw when no body provided', () => { - const testEvent = - TestEvents.apiGatewayProxyV2Event as APIGatewayProxyEventV2; - testEvent.body = undefined; + it('should return original event when body does not match schema', () => { + const testEvent = + TestEvents.lambdaFunctionUrlEvent as APIGatewayProxyEventV2; + testEvent.body = JSON.stringify({ foo: 'bar' }); - expect(() => lambdaFunctionUrlEnvelope(testEvent, TestSchema)).toThrow(); + expect( + LambdaFunctionUrlEnvelope.safeParse(testEvent, TestSchema) + ).toEqual({ + success: false, + error: expect.any(Error), + originalEvent: testEvent, + }); + }); }); }); diff --git a/packages/parser/tests/unit/envelopes/sns.test.ts b/packages/parser/tests/unit/envelopes/sns.test.ts index 217ec29c92..c1e9b67bee 100644 --- a/packages/parser/tests/unit/envelopes/sns.test.ts +++ b/packages/parser/tests/unit/envelopes/sns.test.ts @@ -4,48 +4,160 @@ * @group unit/parser/envelopes */ -import { z } from 'zod'; +import { z, ZodError } from 'zod'; import { generateMock } from '@anatine/zod-mock'; import { SNSEvent, SQSEvent } from 'aws-lambda'; import { TestEvents, TestSchema } from '../schema/utils.js'; -import { snsEnvelope, snsSqsEnvelope } from '../../../src/envelopes'; +import { SnsEnvelope, SnsSqsEnvelope } from '../../../src/envelopes/index.js'; -describe('SNS Envelope', () => { - it('should parse custom schema in envelope', () => { - const testEvent = TestEvents.snsEvent as SNSEvent; +describe('Sns and SQS Envelope', () => { + describe('SnsSqsEnvelope parse', () => { + it('should parse sqs inside sns envelope', () => { + const snsSqsTestEvent = TestEvents.snsSqsEvent as SQSEvent; - const testRecords = [] as z.infer[]; + const data = generateMock(TestSchema); + const snsEvent = JSON.parse(snsSqsTestEvent.Records[0].body); + snsEvent.Message = JSON.stringify(data); - testEvent.Records.map((record) => { - const value = generateMock(TestSchema); - testRecords.push(value); - record.Sns.Message = JSON.stringify(value); - }); + snsSqsTestEvent.Records[0].body = JSON.stringify(snsEvent); - expect(snsEnvelope(testEvent, TestSchema)).toEqual(testRecords); + expect(SnsSqsEnvelope.parse(snsSqsTestEvent, TestSchema)).toEqual([data]); + }); }); + describe('SnsSqsEnvelope safeParse', () => { + it('should parse sqs inside sns envelope', () => { + const snsSqsTestEvent = TestEvents.snsSqsEvent as SQSEvent; + + const data = generateMock(TestSchema); + const snsEvent = JSON.parse(snsSqsTestEvent.Records[0].body); + snsEvent.Message = JSON.stringify(data); + + snsSqsTestEvent.Records[0].body = JSON.stringify(snsEvent); + + expect(SnsSqsEnvelope.safeParse(snsSqsTestEvent, TestSchema)).toEqual({ + success: true, + data: [data], + }); + }); + it('should return error when envelope is not valid', () => { + expect(SnsSqsEnvelope.safeParse({ foo: 'bar' }, TestSchema)).toEqual({ + success: false, + error: expect.any(Error), + originalEvent: { foo: 'bar' }, + }); + }); + it('should return error if message does not match schema', () => { + const snsSqsTestEvent = TestEvents.snsSqsEvent as SQSEvent; + + const snsEvent = JSON.parse(snsSqsTestEvent.Records[0].body); + snsEvent.Message = JSON.stringify({ + foo: 'bar', + }); + + snsSqsTestEvent.Records[0].body = JSON.stringify(snsEvent); - it('should throw if message does not macht schema', () => { - const testEvent = TestEvents.snsEvent as SNSEvent; + expect(SnsSqsEnvelope.safeParse(snsSqsTestEvent, TestSchema)).toEqual({ + success: false, + error: expect.any(ZodError), + originalEvent: snsSqsTestEvent, + }); + }); + it('should return error if sns message is not valid', () => { + const snsSqsTestEvent = TestEvents.snsSqsEvent as SQSEvent; - testEvent.Records.map((record) => { - record.Sns.Message = JSON.stringify({ + snsSqsTestEvent.Records[0].body = JSON.stringify({ foo: 'bar', }); + + expect(SnsSqsEnvelope.safeParse(snsSqsTestEvent, TestSchema)).toEqual({ + success: false, + error: expect.any(ZodError), + originalEvent: snsSqsTestEvent, + }); }); + it('should return error if JSON parse fails for record.body', () => { + const snsSqsTestEvent = TestEvents.snsSqsEvent as SQSEvent; - expect(() => snsEnvelope(testEvent, TestSchema)).toThrowError(); + snsSqsTestEvent.Records[0].body = 'not a json string'; + + expect(SnsSqsEnvelope.safeParse(snsSqsTestEvent, TestSchema)).toEqual({ + success: false, + error: expect.any(Error), + originalEvent: snsSqsTestEvent, + }); + }); }); +}); +describe('SnsEnvelope', () => { + describe('parse', () => { + it('should parse custom schema in envelope', () => { + const testEvent = TestEvents.snsEvent as SNSEvent; - it('should parse sqs inside sns envelope', () => { - const snsSqsTestEvent = TestEvents.snsSqsEvent as SQSEvent; + const testRecords = [] as z.infer[]; - const data = generateMock(TestSchema); - const snsEvent = JSON.parse(snsSqsTestEvent.Records[0].body); - snsEvent.Message = JSON.stringify(data); + testEvent.Records.map((record) => { + const value = generateMock(TestSchema); + testRecords.push(value); + record.Sns.Message = JSON.stringify(value); + }); - snsSqsTestEvent.Records[0].body = JSON.stringify(snsEvent); + expect(SnsEnvelope.parse(testEvent, TestSchema)).toEqual(testRecords); + }); + + it('should throw if message does not macht schema', () => { + const testEvent = TestEvents.snsEvent as SNSEvent; + + testEvent.Records.map((record) => { + record.Sns.Message = JSON.stringify({ + foo: 'bar', + }); + }); + + expect(() => SnsEnvelope.parse(testEvent, TestSchema)).toThrow(); + }); + it('should throw if envelope is not valid', () => { + expect(() => SnsEnvelope.parse({ foo: 'bar' }, TestSchema)).toThrow(); + }); + }); + describe('safeParse', () => { + it('should parse custom schema in envelope', () => { + const testEvent = TestEvents.snsEvent as SNSEvent; + + const testRecords = [] as z.infer[]; + + testEvent.Records.map((record) => { + const value = generateMock(TestSchema); + testRecords.push(value); + record.Sns.Message = JSON.stringify(value); + }); - expect(snsSqsEnvelope(snsSqsTestEvent, TestSchema)).toEqual([data]); + expect(SnsEnvelope.safeParse(testEvent, TestSchema)).toEqual({ + success: true, + data: testRecords, + }); + }); + + it('should return error when message does not macht schema', () => { + const testEvent = TestEvents.snsEvent as SNSEvent; + + testEvent.Records.map((record) => { + record.Sns.Message = JSON.stringify({ + foo: 'bar', + }); + }); + + expect(SnsEnvelope.safeParse(testEvent, TestSchema)).toEqual({ + success: false, + error: expect.any(ZodError), + originalEvent: testEvent, + }); + }); + it('should return error when envelope is not valid', () => { + expect(SnsEnvelope.safeParse({ foo: 'bar' }, TestSchema)).toEqual({ + success: false, + error: expect.any(Error), + originalEvent: { foo: 'bar' }, + }); + }); }); }); diff --git a/packages/parser/tests/unit/envelopes/sqs.test.ts b/packages/parser/tests/unit/envelopes/sqs.test.ts index 041904ebc1..4d1ab3a419 100644 --- a/packages/parser/tests/unit/envelopes/sqs.test.ts +++ b/packages/parser/tests/unit/envelopes/sqs.test.ts @@ -7,39 +7,64 @@ import { generateMock } from '@anatine/zod-mock'; import { TestEvents, TestSchema } from '../schema/utils.js'; import { SQSEvent } from 'aws-lambda'; -import { sqsEnvelope } from '../../../src/envelopes'; +import { SqsEnvelope } from '../../../src/envelopes/sqs.js'; +import { ZodError } from 'zod'; describe('SqsEnvelope ', () => { - it('should parse custom schema in envelope', () => { - const mock = generateMock(TestSchema); + describe('parse', () => { + it('should parse custom schema in envelope', () => { + const mock = generateMock(TestSchema); - const sqsEvent = TestEvents.sqsEvent as SQSEvent; - sqsEvent.Records[0].body = JSON.stringify(mock); - sqsEvent.Records[1].body = JSON.stringify(mock); + const sqsEvent = TestEvents.sqsEvent as SQSEvent; + sqsEvent.Records[0].body = JSON.stringify(mock); + sqsEvent.Records[1].body = JSON.stringify(mock); - const resp = sqsEnvelope(sqsEvent, TestSchema); - expect(resp).toEqual([mock, mock]); - }); + const resp = SqsEnvelope.parse(sqsEvent, TestSchema); + expect(resp).toEqual([mock, mock]); + }); + + it('should throw error if invalid keys for a schema', () => { + expect(() => { + SqsEnvelope.parse({ Records: [{ foo: 'bar' }] }, TestSchema); + }).toThrow(); + }); - it('should throw error if invalid keys for a schema', () => { - expect(() => { - sqsEnvelope({ Records: [{ foo: 'bar' }] }, TestSchema); - }).toThrow(); + it('should throw if invalid envelope', () => { + expect(() => { + SqsEnvelope.parse({ foo: 'bar' }, TestSchema); + }).toThrow(); + }); }); + describe('safeParse', () => { + it('should parse custom schema in envelope', () => { + const mock = generateMock(TestSchema); + + const sqsEvent = TestEvents.sqsEvent as SQSEvent; + sqsEvent.Records[0].body = JSON.stringify(mock); + sqsEvent.Records[1].body = JSON.stringify(mock); + + expect(SqsEnvelope.safeParse(sqsEvent, TestSchema)).toEqual({ + success: true, + data: [mock, mock], + }); + }); + + it('should return error if event does not match schema', () => { + const sqsEvent = TestEvents.sqsEvent as SQSEvent; + sqsEvent.Records[0].body = JSON.stringify({ foo: 'bar' }); + expect(SqsEnvelope.safeParse(sqsEvent, TestSchema)).toEqual({ + success: false, + error: expect.any(ZodError), + originalEvent: sqsEvent, + }); + }); - it('should throw error if invalid values for a schema', () => { - expect(() => { - sqsEnvelope( - { - Records: [ - { - name: 'foo', - age: 17, - }, - ], - }, - TestSchema - ); - }).toThrow(); + it('should return error if envelope is invalid', () => { + expect(SqsEnvelope.safeParse({ foo: 'bar' }, TestSchema)).toEqual({ + success: false, + error: expect.any(ZodError), + originalEvent: { foo: 'bar' }, + }); + }); }); }); diff --git a/packages/parser/tests/unit/envelopes/vpc-lattice.test.ts b/packages/parser/tests/unit/envelopes/vpc-lattice.test.ts index 23af974009..a4282064d2 100644 --- a/packages/parser/tests/unit/envelopes/vpc-lattice.test.ts +++ b/packages/parser/tests/unit/envelopes/vpc-lattice.test.ts @@ -6,33 +6,92 @@ import { generateMock } from '@anatine/zod-mock'; import { TestEvents, TestSchema } from '../schema/utils.js'; -import { VpcLatticeSchema } from '../../../src/schemas'; -import { z } from 'zod'; -import { vpcLatticeEnvelope } from '../../../src/envelopes'; +import { VpcLatticeEnvelope } from '../../../src/envelopes/index.js'; +import { VpcLatticeEvent } from '../../../src/types/index.js'; -describe('VPC Lattice envelope', () => { - it('should parse VPC Lattice event', () => { - const mock = generateMock(TestSchema); - const testEvent = TestEvents.vpcLatticeEvent as z.infer< - typeof VpcLatticeSchema - >; +describe('VpcLatticeEnvelope', () => { + describe('parse', () => { + it('should parse VPC Lattice event', () => { + const mock = generateMock(TestSchema); + const testEvent = TestEvents.vpcLatticeEvent as VpcLatticeEvent; - testEvent.body = JSON.stringify(mock); + testEvent.body = JSON.stringify(mock); - const resp = vpcLatticeEnvelope(testEvent, TestSchema); + const resp = VpcLatticeEnvelope.parse(testEvent, TestSchema); - expect(resp).toEqual(mock); + expect(resp).toEqual(mock); + }); + + it('should parse VPC Lattice event with trailing slash', () => { + const mock = generateMock(TestSchema); + const testEvent = + TestEvents.vpcLatticeEventPathTrailingSlash as VpcLatticeEvent; + + testEvent.body = JSON.stringify(mock); + + const resp = VpcLatticeEnvelope.parse(testEvent, TestSchema); + expect(resp).toEqual(mock); + }); + + it('should throw if event is not a VPC Lattice event', () => { + expect(() => + VpcLatticeEnvelope.parse({ foo: 'bar' }, TestSchema) + ).toThrow(); + }); + + it('should throw if body does not match schema', () => { + const testEvent = TestEvents.vpcLatticeEvent as VpcLatticeEvent; + + testEvent.body = JSON.stringify({ foo: 'bar' }); + + expect(() => VpcLatticeEnvelope.parse(testEvent, TestSchema)).toThrow(); + }); }); - it('should parse VPC Lattice event with trailing slash', () => { - const mock = generateMock(TestSchema); - const testEvent = TestEvents.vpcLatticeEventPathTrailingSlash as z.infer< - typeof VpcLatticeSchema - >; + describe('safeParse', () => { + it('should parse VPC Lattice event', () => { + const mock = generateMock(TestSchema); + const testEvent = TestEvents.vpcLatticeEvent as VpcLatticeEvent; + + testEvent.body = JSON.stringify(mock); + + const resp = VpcLatticeEnvelope.safeParse(testEvent, TestSchema); + + expect(resp).toEqual({ success: true, data: mock }); + }); + + it('should parse VPC Lattice event with trailing slash', () => { + const mock = generateMock(TestSchema); + const testEvent = + TestEvents.vpcLatticeEventPathTrailingSlash as VpcLatticeEvent; + + testEvent.body = JSON.stringify(mock); + + const resp = VpcLatticeEnvelope.safeParse(testEvent, TestSchema); + expect(resp).toEqual({ success: true, data: mock }); + }); + + it('should return error if event is not a VPC Lattice event', () => { + const resp = VpcLatticeEnvelope.safeParse({ foo: 'bar' }, TestSchema); + + expect(resp).toEqual({ + success: false, + error: expect.any(Error), + originalEvent: { foo: 'bar' }, + }); + }); + + it('should return error if body does not match schema', () => { + const testEvent = TestEvents.vpcLatticeEvent as VpcLatticeEvent; - testEvent.body = JSON.stringify(mock); + testEvent.body = JSON.stringify({ foo: 'bar' }); - const resp = vpcLatticeEnvelope(testEvent, TestSchema); - expect(resp).toEqual(mock); + const resp = VpcLatticeEnvelope.safeParse(testEvent, TestSchema); + expect(resp).toEqual({ + success: false, + error: expect.any(Error), + originalEvent: testEvent, + }); + }); }); }); diff --git a/packages/parser/tests/unit/envelopes/vpc-latticev2.test.ts b/packages/parser/tests/unit/envelopes/vpc-latticev2.test.ts index bc260f197b..6f615178ec 100644 --- a/packages/parser/tests/unit/envelopes/vpc-latticev2.test.ts +++ b/packages/parser/tests/unit/envelopes/vpc-latticev2.test.ts @@ -5,34 +5,93 @@ */ import { generateMock } from '@anatine/zod-mock'; -import { VpcLatticeSchema } from '../../../src/schemas'; -import { z } from 'zod'; import { TestEvents, TestSchema } from '../schema/utils.js'; -import { vpcLatticeV2Envelope } from '../../../src/envelopes'; +import { VpcLatticeV2Envelope } from '../../../src/envelopes/index.js'; +import { VpcLatticeEventV2 } from '../../../src/types/index.js'; -describe('VPC Lattice envelope', () => { - it('should parse VPC Lattice event', () => { - const mock = generateMock(TestSchema); - const testEvent = TestEvents.vpcLatticeV2Event as z.infer< - typeof VpcLatticeSchema - >; +describe('VpcLatticeV2Envelope2', () => { + describe('parse', () => { + it('should parse VPC Lattice event', () => { + const mock = generateMock(TestSchema); + const testEvent = TestEvents.vpcLatticeV2Event as VpcLatticeEventV2; - testEvent.body = JSON.stringify(mock); + testEvent.body = JSON.stringify(mock); - const resp = vpcLatticeV2Envelope(testEvent, TestSchema); + const resp = VpcLatticeV2Envelope.parse(testEvent, TestSchema); - expect(resp).toEqual(mock); + expect(resp).toEqual(mock); + }); + + it('should parse VPC Lattice event with trailing slash', () => { + const mock = generateMock(TestSchema); + const testEvent = + TestEvents.vpcLatticeEventV2PathTrailingSlash as VpcLatticeEventV2; + + testEvent.body = JSON.stringify(mock); + + const resp = VpcLatticeV2Envelope.parse(testEvent, TestSchema); + expect(resp).toEqual(mock); + }); + + it('should throw if event is not a VPC Lattice event', () => { + expect(() => + VpcLatticeV2Envelope.parse({ foo: 'bar' }, TestSchema) + ).toThrow(); + }); + + it('should throw if body does not match schema', () => { + const testEvent = TestEvents.vpcLatticeV2Event as VpcLatticeEventV2; + + testEvent.body = JSON.stringify({ foo: 'bar' }); + + expect(() => VpcLatticeV2Envelope.parse(testEvent, TestSchema)).toThrow(); + }); }); - it('should parse VPC Lattice event with trailing slash', () => { - const mock = generateMock(TestSchema); - const testEvent = TestEvents.vpcLatticeEventV2PathTrailingSlash as z.infer< - typeof VpcLatticeSchema - >; + describe('safeParse', () => { + it('should parse VPC Lattice event', () => { + const mock = generateMock(TestSchema); + const testEvent = TestEvents.vpcLatticeV2Event as VpcLatticeEventV2; + + testEvent.body = JSON.stringify(mock); + + const resp = VpcLatticeV2Envelope.safeParse(testEvent, TestSchema); + + expect(resp).toEqual({ success: true, data: mock }); + }); + + it('should parse VPC Lattice event with trailing slash', () => { + const mock = generateMock(TestSchema); + const testEvent = + TestEvents.vpcLatticeEventV2PathTrailingSlash as VpcLatticeEventV2; + + testEvent.body = JSON.stringify(mock); + + const resp = VpcLatticeV2Envelope.safeParse(testEvent, TestSchema); + expect(resp).toEqual({ success: true, data: mock }); + }); + + it('should return error if event is not a VPC Lattice event', () => { + const resp = VpcLatticeV2Envelope.safeParse({ foo: 'bar' }, TestSchema); + + expect(resp).toEqual({ + success: false, + error: expect.any(Error), + originalEvent: { foo: 'bar' }, + }); + }); + + it('should return error if body does not match schema', () => { + const testEvent = TestEvents.vpcLatticeV2Event as VpcLatticeEventV2; - testEvent.body = JSON.stringify(mock); + testEvent.body = JSON.stringify({ foo: 'bar' }); - const resp = vpcLatticeV2Envelope(testEvent, TestSchema); - expect(resp).toEqual(mock); + const resp = VpcLatticeV2Envelope.safeParse(testEvent, TestSchema); + expect(resp).toEqual({ + success: false, + error: expect.any(Error), + originalEvent: testEvent, + }); + }); }); }); diff --git a/packages/parser/tests/unit/parser.decorator.test.ts b/packages/parser/tests/unit/parser.decorator.test.ts index 7e4d7e9aa6..1e05efa510 100644 --- a/packages/parser/tests/unit/parser.decorator.test.ts +++ b/packages/parser/tests/unit/parser.decorator.test.ts @@ -4,26 +4,27 @@ * @group unit/parser */ -import { LambdaInterface } from '@aws-lambda-powertools/commons/lib/esm/types'; -import { Context, EventBridgeEvent } from 'aws-lambda'; -import { parser } from '../../src'; +import type { LambdaInterface } from '@aws-lambda-powertools/commons/lib/esm/types'; +import { Context } from 'aws-lambda'; +import { parser } from '../../src/index.js'; import { TestSchema, TestEvents } from './schema/utils'; import { generateMock } from '@anatine/zod-mock'; -import { eventBridgeEnvelope } from '../../src/envelopes'; -import { EventBridgeSchema } from '../../src/schemas'; -import { z } from 'zod'; +import { EventBridgeSchema } from '../../src/schemas/index.js'; +import { z, ZodError } from 'zod'; +import { ParsedResult, EventBridgeEvent } from '../../src/types'; +import { EventBridgeEnvelope } from '../../src/envelopes/index.js'; describe('Parser Decorator', () => { const customEventBridgeSchema = EventBridgeSchema.extend({ detail: TestSchema, }); - type TestSchema = z.infer; + type TestEvent = z.infer; class TestClass implements LambdaInterface { @parser({ schema: TestSchema }) public async handler( - event: TestSchema, + event: TestEvent, _context: Context ): Promise { return event; @@ -37,23 +38,46 @@ describe('Parser Decorator', () => { return event; } - @parser({ schema: TestSchema, envelope: eventBridgeEnvelope }) + @parser({ schema: TestSchema, envelope: EventBridgeEnvelope }) public async handlerWithParserCallsAnotherMethod( - event: unknown, + event: TestEvent, _context: Context ): Promise { - return this.anotherMethod(event as TestSchema); + return this.anotherMethod(event); } - @parser({ envelope: eventBridgeEnvelope, schema: TestSchema }) + @parser({ schema: TestSchema, envelope: EventBridgeEnvelope }) public async handlerWithSchemaAndEnvelope( - event: unknown, + event: TestEvent, _context: Context ): Promise { return event; } - private async anotherMethod(event: TestSchema): Promise { + @parser({ + schema: TestSchema, + safeParse: true, + }) + public async handlerWithSchemaAndSafeParse( + event: ParsedResult, + _context: Context + ): Promise { + return event; + } + + @parser({ + schema: TestSchema, + envelope: EventBridgeEnvelope, + safeParse: true, + }) + public async harndlerWithEnvelopeAndSafeParse( + event: ParsedResult, + _context: Context + ): Promise { + return event; + } + + private async anotherMethod(event: TestEvent): Promise { return event; } } @@ -70,13 +94,12 @@ describe('Parser Decorator', () => { it('should parse custom schema with envelope event', async () => { const customPayload = generateMock(TestSchema); - const testEvent = TestEvents.eventBridgeEvent as EventBridgeEvent< - string, - unknown - >; + const testEvent = TestEvents.eventBridgeEvent as EventBridgeEvent; testEvent.detail = customPayload; const resp = await lambda.handlerWithSchemaAndEnvelope( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore testEvent, {} as Context ); @@ -102,17 +125,77 @@ describe('Parser Decorator', () => { it('should parse and call private async method', async () => { const customPayload = generateMock(TestSchema); - const testEvent = TestEvents.eventBridgeEvent as EventBridgeEvent< - string, - unknown - >; + const testEvent = TestEvents.eventBridgeEvent as EventBridgeEvent; testEvent.detail = customPayload; const resp = await lambda.handlerWithParserCallsAnotherMethod( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore testEvent, {} as Context ); expect(resp).toEqual(customPayload); }); + + it('should parse event with schema and safeParse', async () => { + const testEvent = generateMock(TestSchema); + + const resp = await lambda.handlerWithSchemaAndSafeParse( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + testEvent, + {} as Context + ); + + expect(resp).toEqual({ + success: true, + data: testEvent, + }); + }); + + it('should parse event with schema and safeParse and return error', async () => { + expect( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + await lambda.handlerWithSchemaAndSafeParse({ foo: 'bar' }, {} as Context) + ).toEqual({ + error: expect.any(ZodError), + success: false, + originalEvent: { foo: 'bar' }, + }); + }); + + it('should parse event with envelope and safeParse', async () => { + const testEvent = generateMock(TestSchema); + const event = TestEvents.eventBridgeEvent as EventBridgeEvent; + event.detail = testEvent; + + const resp = await lambda.harndlerWithEnvelopeAndSafeParse( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + event, + {} as Context + ); + + expect(resp).toEqual({ + success: true, + data: testEvent, + }); + }); + + it('should parse event with envelope and safeParse and return error', async () => { + expect( + await lambda.harndlerWithEnvelopeAndSafeParse( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + { foo: 'bar' }, + {} as Context + ) + ).toEqual({ + error: expect.any(ZodError), + success: false, + originalEvent: { foo: 'bar' }, + }); + }); }); diff --git a/packages/parser/tests/unit/parser.middy.test.ts b/packages/parser/tests/unit/parser.middy.test.ts index 0e53c4d5ea..d8dd4ae1b1 100644 --- a/packages/parser/tests/unit/parser.middy.test.ts +++ b/packages/parser/tests/unit/parser.middy.test.ts @@ -8,10 +8,11 @@ import middy from '@middy/core'; import { Context } from 'aws-lambda'; import { parser } from '../../src/middleware/parser.js'; import { generateMock } from '@anatine/zod-mock'; -import { SqsSchema } from '../../src/schemas'; +import { SqsSchema } from '../../src/schemas/index.js'; import { z, type ZodSchema } from 'zod'; -import { sqsEnvelope } from '../../src/envelopes'; -import { TestSchema } from './schema/utils'; +import { SqsEnvelope, EventBridgeEnvelope } from '../../src/envelopes/index.js'; +import { TestSchema, TestEvents } from './schema/utils'; +import { EventBridgeEvent } from '../../src/types/index.js'; describe('Middleware: parser', () => { type schema = z.infer; @@ -23,13 +24,13 @@ describe('Middleware: parser', () => { }; describe(' when envelope is provided ', () => { - const middyfiedHandler = middy(handler).use( - parser({ schema: TestSchema, envelope: sqsEnvelope }) + const middyfiedHandlerSchemaEnvelope = middy(handler).use( + parser({ schema: TestSchema, envelope: SqsEnvelope }) ); it('should parse request body with schema and envelope', async () => { const bodyMock = generateMock(TestSchema); - parser({ schema: TestSchema, envelope: sqsEnvelope }); + parser({ schema: TestSchema, envelope: SqsEnvelope }); const event = generateMock(SqsSchema, { stringMap: { @@ -37,7 +38,10 @@ describe('Middleware: parser', () => { }, }); - const result = (await middyfiedHandler(event, {} as Context)) as schema[]; + const result = (await middyfiedHandlerSchemaEnvelope( + event, + {} as Context + )) as schema[]; result.forEach((item) => { expect(item).toEqual(bodyMock); }); @@ -45,8 +49,11 @@ describe('Middleware: parser', () => { it('should throw when envelope does not match', async () => { await expect(async () => { - await middyfiedHandler({ name: 'John', age: 18 }, {} as Context); - }).rejects.toThrowError(); + await middyfiedHandlerSchemaEnvelope( + { name: 'John', age: 18 }, + {} as Context + ); + }).rejects.toThrow(); }); it('should throw when schema does not match', async () => { @@ -56,14 +63,16 @@ describe('Middleware: parser', () => { }, }); - await expect(middyfiedHandler(event, {} as Context)).rejects.toThrow(); + await expect( + middyfiedHandlerSchemaEnvelope(event, {} as Context) + ).rejects.toThrow(); }); it('should throw when provided schema is invalid', async () => { const middyfiedHandler = middy(handler).use( - parser({ schema: {} as ZodSchema, envelope: sqsEnvelope }) + parser({ schema: {} as ZodSchema, envelope: SqsEnvelope }) ); - await expect(middyfiedHandler(42, {} as Context)).rejects.toThrowError(); + await expect(middyfiedHandler(42, {} as Context)).rejects.toThrow(); }); it('should throw when envelope is correct but schema is invalid', async () => { const event = generateMock(SqsSchema, { @@ -73,12 +82,10 @@ describe('Middleware: parser', () => { }); const middyfiedHandler = middy(handler).use( - parser({ schema: {} as ZodSchema, envelope: sqsEnvelope }) + parser({ schema: {} as ZodSchema, envelope: SqsEnvelope }) ); - await expect( - middyfiedHandler(event, {} as Context) - ).rejects.toThrowError(); + await expect(middyfiedHandler(event, {} as Context)).rejects.toThrow(); }); }); @@ -117,7 +124,69 @@ describe('Middleware: parser', () => { await expect( middyfiedHandler({ foo: 'bar' }, {} as Context) - ).rejects.toThrowError(); + ).rejects.toThrow(); + }); + + it('should return the event when safeParse is true', async () => { + const event = { name: 'John', age: 18 }; + const middyfiedHandler = middy(handler).use( + parser({ schema: TestSchema, safeParse: true }) + ); + + expect(await middyfiedHandler(event, {} as Context)).toEqual({ + success: true, + data: event, + }); + }); + + it('should return error when safeParse is true and schema does not match', async () => { + const middyfiedHandler = middy(handler).use( + parser({ schema: TestSchema, safeParse: true }) + ); + + expect(await middyfiedHandler(42, {} as Context)).toEqual({ + success: false, + error: expect.any(Error), + originalEvent: 42, + }); + }); + + it('should return event when envelope and safeParse are true', async () => { + const detail = generateMock(TestSchema); + const event = TestEvents.eventBridgeEvent as EventBridgeEvent; + + event.detail = detail; + + const middyfiedHandler = middy(handler).use( + parser({ + schema: TestSchema, + envelope: EventBridgeEnvelope, + safeParse: true, + }) + ); + + expect(await middyfiedHandler(event, {} as Context)).toEqual({ + success: true, + data: detail, + }); + }); + + it('should return error when envelope and safeParse are true and schema does not match', async () => { + const event = TestEvents.eventBridgeEvent as EventBridgeEvent; + + const middyfiedHandler = middy(handler).use( + parser({ + schema: TestSchema, + envelope: EventBridgeEnvelope, + safeParse: true, + }) + ); + + expect(await middyfiedHandler(event, {} as Context)).toEqual({ + success: false, + error: expect.any(Error), + originalEvent: event, + }); }); }); }); diff --git a/packages/parser/tests/unit/schema/alb.test.ts b/packages/parser/tests/unit/schema/alb.test.ts index 3c39b7f734..6984f56f6d 100644 --- a/packages/parser/tests/unit/schema/alb.test.ts +++ b/packages/parser/tests/unit/schema/alb.test.ts @@ -3,7 +3,7 @@ * * @group unit/parser/schema/ */ -import { AlbSchema, AlbMultiValueHeadersSchema } from '../../../src/schemas'; +import { AlbSchema, AlbMultiValueHeadersSchema } from '../../../src/schemas/'; import { TestEvents } from './utils.js'; describe('ALB ', () => { diff --git a/packages/parser/tests/unit/schema/apigwv2.test.ts b/packages/parser/tests/unit/schema/apigwv2.test.ts index 1a6b1f9670..1ebb547c7f 100644 --- a/packages/parser/tests/unit/schema/apigwv2.test.ts +++ b/packages/parser/tests/unit/schema/apigwv2.test.ts @@ -4,7 +4,7 @@ * @group unit/parser/schema/ */ -import { APIGatewayProxyEventV2Schema } from '../../../src/schemas'; +import { APIGatewayProxyEventV2Schema } from '../../../src/schemas/'; import { TestEvents } from './utils.js'; describe('API GW v2 ', () => { diff --git a/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts b/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts index a04c0784b8..7b4df56201 100644 --- a/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts +++ b/packages/parser/tests/unit/schema/cloudformation-custom-resource.test.ts @@ -8,7 +8,7 @@ import { CloudFormationCustomResourceCreateSchema, CloudFormationCustomResourceUpdateSchema, CloudFormationCustomResourceDeleteSchema, -} from '../../../src/schemas'; +} from '../../../src/schemas/'; import { TestEvents } from './utils.js'; describe('CloudFormationCustomResource ', () => { diff --git a/packages/parser/tests/unit/schema/cloudwatch.test.ts b/packages/parser/tests/unit/schema/cloudwatch.test.ts index f212bb6587..e126bdb7fb 100644 --- a/packages/parser/tests/unit/schema/cloudwatch.test.ts +++ b/packages/parser/tests/unit/schema/cloudwatch.test.ts @@ -4,7 +4,7 @@ * @group unit/parser/schema/ */ -import { CloudWatchLogsSchema } from '../../../src/schemas'; +import { CloudWatchLogsSchema } from '../../../src/schemas/'; import { TestEvents } from './utils.js'; describe('CloudWatchLogs ', () => { diff --git a/packages/parser/tests/unit/schema/dynamodb.test.ts b/packages/parser/tests/unit/schema/dynamodb.test.ts index c0de0ff56a..f0d90fbc5b 100644 --- a/packages/parser/tests/unit/schema/dynamodb.test.ts +++ b/packages/parser/tests/unit/schema/dynamodb.test.ts @@ -4,7 +4,7 @@ * @group unit/parser/schema/ */ -import { DynamoDBStreamSchema } from '../../../src/schemas'; +import { DynamoDBStreamSchema } from '../../../src/schemas/'; import { TestEvents } from './utils.js'; describe('DynamoDB ', () => { diff --git a/packages/parser/tests/unit/schema/eventbridge.test.ts b/packages/parser/tests/unit/schema/eventbridge.test.ts index 69594f8c66..4423318874 100644 --- a/packages/parser/tests/unit/schema/eventbridge.test.ts +++ b/packages/parser/tests/unit/schema/eventbridge.test.ts @@ -4,7 +4,7 @@ * @group unit/parser/schema/ */ -import { EventBridgeSchema } from '../../../src/schemas'; +import { EventBridgeSchema } from '../../../src/schemas/'; import { TestEvents } from './utils.js'; describe('EventBridge ', () => { diff --git a/packages/parser/tests/unit/schema/kafka.test.ts b/packages/parser/tests/unit/schema/kafka.test.ts index 952a4eb21b..c6aab47348 100644 --- a/packages/parser/tests/unit/schema/kafka.test.ts +++ b/packages/parser/tests/unit/schema/kafka.test.ts @@ -7,7 +7,7 @@ import { KafkaMskEventSchema, KafkaSelfManagedEventSchema, -} from '../../../src/schemas'; +} from '../../../src/schemas/'; import { TestEvents } from './utils.js'; describe('Kafka ', () => { diff --git a/packages/parser/tests/unit/schema/kinesis.test.ts b/packages/parser/tests/unit/schema/kinesis.test.ts index a51b960450..31c4400757 100644 --- a/packages/parser/tests/unit/schema/kinesis.test.ts +++ b/packages/parser/tests/unit/schema/kinesis.test.ts @@ -8,7 +8,7 @@ import { KinesisDataStreamSchema, KinesisFirehoseSchema, KinesisFirehoseSqsSchema, -} from '../../../src/schemas'; +} from '../../../src/schemas/'; import { TestEvents } from './utils.js'; describe('Kinesis ', () => { diff --git a/packages/parser/tests/unit/schema/lambda.test.ts b/packages/parser/tests/unit/schema/lambda.test.ts index cf43eb4fd2..cfef867657 100644 --- a/packages/parser/tests/unit/schema/lambda.test.ts +++ b/packages/parser/tests/unit/schema/lambda.test.ts @@ -4,7 +4,7 @@ * @group unit/parser/schema/ */ -import { LambdaFunctionUrlSchema } from '../../../src/schemas'; +import { LambdaFunctionUrlSchema } from '../../../src/schemas/'; import { TestEvents } from './utils.js'; describe('Lambda ', () => { diff --git a/packages/parser/tests/unit/schema/s3.test.ts b/packages/parser/tests/unit/schema/s3.test.ts index 7d23da0d8c..72e3ba74dc 100644 --- a/packages/parser/tests/unit/schema/s3.test.ts +++ b/packages/parser/tests/unit/schema/s3.test.ts @@ -9,7 +9,7 @@ import { S3SqsEventNotificationSchema, S3Schema, S3ObjectLambdaEventSchema, -} from '../../../src/schemas'; +} from '../../../src/schemas/'; import { TestEvents } from './utils.js'; describe('S3 ', () => { diff --git a/packages/parser/tests/unit/schema/ses.test.ts b/packages/parser/tests/unit/schema/ses.test.ts index bc7f17f53c..010fa4872c 100644 --- a/packages/parser/tests/unit/schema/ses.test.ts +++ b/packages/parser/tests/unit/schema/ses.test.ts @@ -4,7 +4,7 @@ * @group unit/parser/schema/ */ -import { SesSchema } from '../../../src/schemas'; +import { SesSchema } from '../../../src/schemas/'; import { TestEvents } from './utils.js'; describe('Schema:', () => { diff --git a/packages/parser/tests/unit/schema/sns.test.ts b/packages/parser/tests/unit/schema/sns.test.ts index c07b98fe07..26a212b7ad 100644 --- a/packages/parser/tests/unit/schema/sns.test.ts +++ b/packages/parser/tests/unit/schema/sns.test.ts @@ -4,7 +4,7 @@ * @group unit/parser/schema/ */ -import { SnsSchema } from '../../../src/schemas'; +import { SnsSchema } from '../../../src/schemas/'; import { TestEvents } from './utils.js'; describe('Schema:', () => { diff --git a/packages/parser/tests/unit/schema/sqs.test.ts b/packages/parser/tests/unit/schema/sqs.test.ts index d228b44cd2..d92f0d73e5 100644 --- a/packages/parser/tests/unit/schema/sqs.test.ts +++ b/packages/parser/tests/unit/schema/sqs.test.ts @@ -4,7 +4,7 @@ * @group unit/parser/schema/ */ -import { SqsSchema } from '../../../src/schemas'; +import { SqsSchema } from '../../../src/schemas/'; import { TestEvents } from './utils.js'; describe('SQS ', () => { diff --git a/packages/parser/tests/unit/schema/vpc-lattice.test.ts b/packages/parser/tests/unit/schema/vpc-lattice.test.ts index 62a67acbed..643714fb47 100644 --- a/packages/parser/tests/unit/schema/vpc-lattice.test.ts +++ b/packages/parser/tests/unit/schema/vpc-lattice.test.ts @@ -4,7 +4,7 @@ * @group unit/parser/schema/ */ -import { VpcLatticeSchema } from '../../../src/schemas'; +import { VpcLatticeSchema } from '../../../src/schemas/'; import { TestEvents } from './utils.js'; describe('VPC Lattice ', () => { diff --git a/packages/parser/tests/unit/schema/vpc-latticev2.test.ts b/packages/parser/tests/unit/schema/vpc-latticev2.test.ts index 0b275e82e3..5e1b6c7343 100644 --- a/packages/parser/tests/unit/schema/vpc-latticev2.test.ts +++ b/packages/parser/tests/unit/schema/vpc-latticev2.test.ts @@ -4,7 +4,7 @@ * @group unit/parser/schema/ */ -import { VpcLatticeV2Schema } from '../../../src/schemas'; +import { VpcLatticeV2Schema } from '../../../src/schemas/'; import { TestEvents } from './utils.js'; describe('VpcLatticeV2 ', () => { diff --git a/packages/testing/CHANGELOG.md b/packages/testing/CHANGELOG.md index 0bd77eabfb..627952f84c 100644 --- a/packages/testing/CHANGELOG.md +++ b/packages/testing/CHANGELOG.md @@ -3,6 +3,65 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2.0.2 (2024-03-05) + +**Note:** Version bump only for package @aws-lambda-powertools/testing-utils + + + + + + +## 2.0.1 (2024-03-04) + +**Note:** Version bump only for package @aws-lambda-powertools/testing-utils + + + + + +# [2.0.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.18.1...v2.0.0) (2024-03-04) + +**Note:** Version bump only for package @aws-lambda-powertools/testing-utils + + + + + +## 1.18.1 (2024-02-20) + +**Note:** Version bump only for package @aws-lambda-powertools/testing-utils + + + + + +## [1.18.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.17.0...v1.18.0) (2024-01-26) + +**Note:** Version bump only for package @aws-lambda-powertools/testing-utils + +## [1.17.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.16.0...v1.17.0) (2023-11-24) + +**maintenance:** drop support for Node.js 14 ([#1664](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1664)) ([e2a0923](https://github.com/aws-powertools/powertools-lambda-typescript/commit/e2a09232f86167b5208be2daf892aa1ea433ce0f)) + +# [1.16.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.15.0...v1.16.0) (2023-11-16) + +**Note:** Version bump only for package @aws-lambda-powertools/testing-utils + +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) + +## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) + +**Note:** Version bump only for package @aws-lambda-powertools/testing-utils + +## [1.14.1](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.0...v1.14.1) (2023-10-31) + +**Note:** Version bump only for package @aws-lambda-powertools/testing-utils + # [1.14.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.13.1...v1.14.0) (2023-09-29) ### Features diff --git a/packages/testing/package.json b/packages/testing/package.json index 247426c843..0e470554b9 100644 --- a/packages/testing/package.json +++ b/packages/testing/package.json @@ -1,6 +1,6 @@ { "name": "@aws-lambda-powertools/testing-utils", - "version": "1.14.0", + "version": "2.0.2", "description": "A package containing utilities to test your serverless workloads", "author": { "name": "Amazon Web Services", @@ -94,10 +94,10 @@ }, "homepage": "https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/packages/testing#readme", "dependencies": { - "@aws-cdk/cli-lib-alpha": "^2.96.1-alpha.0", - "@aws-sdk/client-lambda": "^3.438.0", - "@smithy/util-utf8": "^2.0.0", - "aws-cdk-lib": "^2.96.1", - "esbuild": "^0.19.3" + "@aws-cdk/cli-lib-alpha": "^2.121.1-alpha.0", + "@aws-sdk/client-lambda": "^3.525.0", + "@smithy/util-utf8": "^2.1.0", + "aws-cdk-lib": "^2.130.0", + "esbuild": "^0.20.1" } } diff --git a/packages/testing/src/TestInvocationLogs.ts b/packages/testing/src/TestInvocationLogs.ts index 0581e0d927..106033a180 100644 --- a/packages/testing/src/TestInvocationLogs.ts +++ b/packages/testing/src/TestInvocationLogs.ts @@ -10,7 +10,7 @@ const CloudWatchLogKeywords = { } as const; class TestInvocationLogs { - public static LEVEL = LogLevel; + public static readonly LEVEL = LogLevel; /** * Array of logs from invocation. diff --git a/packages/testing/src/constants.ts b/packages/testing/src/constants.ts index 66b7bb2466..0699c4efb4 100644 --- a/packages/testing/src/constants.ts +++ b/packages/testing/src/constants.ts @@ -3,14 +3,15 @@ import { Runtime, Architecture } from 'aws-cdk-lib/aws-lambda'; /** * The default AWS Lambda runtime to use when none is provided. */ -const defaultRuntime = 'nodejs18x'; +const defaultRuntime = 'nodejs20x'; /** * The AWS Lambda runtimes that are supported by the project. */ const TEST_RUNTIMES = { nodejs16x: Runtime.NODEJS_16_X, - [defaultRuntime]: Runtime.NODEJS_18_X, + nodejs18x: Runtime.NODEJS_18_X, + [defaultRuntime]: Runtime.NODEJS_20_X, } as const; /** diff --git a/packages/tracer/CHANGELOG.md b/packages/tracer/CHANGELOG.md index b01696a2aa..83eabd111e 100644 --- a/packages/tracer/CHANGELOG.md +++ b/packages/tracer/CHANGELOG.md @@ -3,6 +3,63 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2.0.2 (2024-03-05) + + +### Bug Fixes + +* **tracer:** modify aws-xray-sdk-core import for js ([#2164](https://github.com/aws-powertools/powertools-lambda-typescript/issues/2164)) ([29630b5](https://github.com/aws-powertools/powertools-lambda-typescript/commit/29630b5b68915ccca1324f3e7ce3e95b85a616be)) + + + + + +## 2.0.1 (2024-03-04) + +**Note:** Version bump only for package @aws-lambda-powertools/tracer + + + + + +# [2.0.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.18.1...v2.0.0) (2024-03-04) + +**Note:** Version bump only for package @aws-lambda-powertools/tracer + + + + + +## 1.18.1 (2024-02-20) + +**Note:** Version bump only for package @aws-lambda-powertools/tracer + + + + + +## [1.17.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.16.0...v1.17.0) (2023-11-24) + +**maintenance:** drop support for Node.js 14 ([#1664](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1664)) ([e2a0923](https://github.com/aws-powertools/powertools-lambda-typescript/commit/e2a09232f86167b5208be2daf892aa1ea433ce0f)) + +# [1.16.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.15.0...v1.16.0) (2023-11-16) + +**Note:** Version bump only for package @aws-lambda-powertools/tracer + +# [1.15.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.2...v1.15.0) (2023-11-14) + +### Features + +- **maintenance:** add support for nodejs20.x runtime ([#1790](https://github.com/aws-powertools/powertools-lambda-typescript/issues/1790)) ([6b9b1bc](https://github.com/aws-powertools/powertools-lambda-typescript/commit/6b9b1bcb9baf4b3d8e0e5ec6709594aca09bb033)) + +## [1.14.2](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.1...v1.14.2) (2023-11-03) + +**Note:** Version bump only for package @aws-lambda-powertools/tracer + +## [1.14.1](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.14.0...v1.14.1) (2023-10-31) + +**Note:** Version bump only for package @aws-lambda-powertools/tracer + # [1.14.0](https://github.com/aws-powertools/powertools-lambda-typescript/compare/v1.13.1...v1.14.0) (2023-09-29) ### Features diff --git a/packages/tracer/README.md b/packages/tracer/README.md index 088675b0e3..dcd1d01588 100644 --- a/packages/tracer/README.md +++ b/packages/tracer/README.md @@ -14,7 +14,7 @@ You can use the library in both TypeScript and JavaScript code bases. - [Getting started](#getting-started) - [Installation](#installation) - [Examples](#examples) - - [Serverless TypeScript Demo application](#serverless-typescript-demo-application) + - [Demo applications](#demo-applications) - [Contribute](#contribute) - [Roadmap](#roadmap) - [Connect](#connect) @@ -62,11 +62,13 @@ Or refer to the installation guide of each utility: * [CDK](https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/examples/cdk) * [SAM](https://github.com/aws-powertools/powertools-lambda-typescript/tree/main/examples/sam) -### Serverless TypeScript Demo application +### Demo applications The [Serverless TypeScript Demo](https://github.com/aws-samples/serverless-typescript-demo) shows how to use Powertools for AWS Lambda (TypeScript). You can find instructions on how to deploy and load test this application in the [repository](https://github.com/aws-samples/serverless-typescript-demo). +The [AWS Lambda performance tuning](https://github.com/aws-samples/optimizations-for-lambda-functions) repository also uses Powertools for AWS Lambda (TypeScript) as well as demonstrating other performance tuning techniques for Lambda functions written in TypeScript. + ## Contribute If you are interested in contributing to this project, please refer to our [Contributing Guidelines](https://github.com/aws-powertools/powertools-lambda-typescript/blob/main/CONTRIBUTING.md). @@ -98,6 +100,8 @@ The following companies, among others, use Powertools: * [Sennder](https://sennder.com/) * [Certible](https://www.certible.com/) * [tecRacer GmbH & Co. KG](https://www.tecracer.com/) +* [AppYourself](https://appyourself.net) +* [Alma Media](https://www.almamedia.fi) ### Sharing your work diff --git a/packages/tracer/package.json b/packages/tracer/package.json index 83baccb7ee..a88df7c2f6 100644 --- a/packages/tracer/package.json +++ b/packages/tracer/package.json @@ -1,6 +1,6 @@ { "name": "@aws-lambda-powertools/tracer", - "version": "1.14.0", + "version": "2.0.2", "description": "The tracer package for the Powertools for AWS Lambda (TypeScript) library", "author": { "name": "Amazon Web Services", @@ -15,6 +15,7 @@ "jest": "jest --detectOpenHandles --verbose", "test:e2e:nodejs16x": "RUNTIME=nodejs16x jest --group=e2e", "test:e2e:nodejs18x": "RUNTIME=nodejs18x jest --group=e2e", + "test:e2e:nodejs20x": "RUNTIME=nodejs20x jest --group=e2e", "test:e2e": "jest --group=e2e", "watch": "jest --watch", "build:cjs": "tsc --build tsconfig.json && echo '{ \"type\": \"commonjs\" }' > lib/cjs/package.json", @@ -31,11 +32,11 @@ "license": "MIT-0", "devDependencies": { "@aws-lambda-powertools/testing-utils": "file:../testing", - "@aws-sdk/client-dynamodb": "^3.438.0", - "@aws-sdk/client-xray": "^3.438.0", - "@types/promise-retry": "^1.1.3", - "aws-sdk": "^2.1484.0", - "axios": "^1.6.0", + "@aws-sdk/client-dynamodb": "^3.525.0", + "@aws-sdk/client-xray": "^3.525.0", + "@types/promise-retry": "^1.1.6", + "aws-sdk": "^2.1568.0", + "axios": "^1.6.7", "promise-retry": "^2.0.1" }, "peerDependencies": { @@ -92,7 +93,7 @@ "url": "https://github.com/aws-powertools/powertools-lambda-typescript/issues" }, "dependencies": { - "@aws-lambda-powertools/commons": "^1.14.0", + "@aws-lambda-powertools/commons": "^2.0.2", "aws-xray-sdk-core": "^3.5.3" }, "keywords": [ diff --git a/packages/tracer/src/Tracer.ts b/packages/tracer/src/Tracer.ts index bd70053287..4b6f40f59a 100644 --- a/packages/tracer/src/Tracer.ts +++ b/packages/tracer/src/Tracer.ts @@ -17,7 +17,9 @@ import type { } from './types/Tracer.js'; import { ProviderService } from './provider/ProviderService.js'; import type { ProviderServiceInterface } from './types/ProviderServiceInterface.js'; -import { type Segment, Subsegment } from 'aws-xray-sdk-core'; +import type { Segment, Subsegment } from 'aws-xray-sdk-core'; +import xraySdk from 'aws-xray-sdk-core'; +const { Subsegment: XraySubsegment } = xraySdk; /** * ## Intro @@ -46,7 +48,8 @@ import { type Segment, Subsegment } from 'aws-xray-sdk-core'; * * @example * ```typescript - * import { captureLambdaHandler, Tracer } from '@aws-lambda-powertools/tracer'; + * import { Tracer } from '@aws-lambda-powertools/tracer'; + * import { captureLambdaHandler } from '@aws-lambda-powertools/tracer/middleware'; * import middy from '@middy/core'; * * const tracer = new Tracer({ serviceName: 'serverlessAirline' }); @@ -69,7 +72,7 @@ import { type Segment, Subsegment } from 'aws-xray-sdk-core'; * @example * ```typescript * import { Tracer } from '@aws-lambda-powertools/tracer'; - * import { LambdaInterface } from '@aws-lambda-powertools/commons'; + * import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; * * const tracer = new Tracer({ serviceName: 'serverlessAirline' }); * @@ -345,7 +348,7 @@ class Tracer extends Utility implements TracerInterface { * @example * ```typescript * import { Tracer } from '@aws-lambda-powertools/tracer'; - * import { LambdaInterface } from '@aws-lambda-powertools/commons'; + * import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; * * const tracer = new Tracer({ serviceName: 'serverlessAirline' }); * @@ -577,7 +580,7 @@ class Tracer extends Utility implements TracerInterface { */ public getSegment(): Segment | Subsegment | undefined { if (!this.isTracingEnabled()) { - return new Subsegment('## Dummy segment'); + return new XraySubsegment('## Dummy segment'); } const segment = this.provider.getSegment(); if (segment === undefined) { diff --git a/packages/tracer/src/config/EnvironmentVariablesService.ts b/packages/tracer/src/config/EnvironmentVariablesService.ts index 5b21241352..d6d9bb7343 100644 --- a/packages/tracer/src/config/EnvironmentVariablesService.ts +++ b/packages/tracer/src/config/EnvironmentVariablesService.ts @@ -14,26 +14,56 @@ class EnvironmentVariablesService private tracerCaptureResponseVariable = 'POWERTOOLS_TRACER_CAPTURE_RESPONSE'; private tracingEnabledVariable = 'POWERTOOLS_TRACE_ENABLED'; + /** + * It returns the value of the AWS_EXECUTION_ENV environment variable. + * + * @returns {string} + */ public getAwsExecutionEnv(): string { return this.get(this.awsExecutionEnv); } + /** + * It returns the value of the POWERTOOLS_TRACER_CAPTURE_HTTPS_REQUESTS environment variable. + * + * @returns {string} + */ public getCaptureHTTPsRequests(): string { return this.get(this.tracerCaptureHTTPsRequestsVariable); } + /** + * It returns the value of the AWS_SAM_LOCAL environment variable. + * + * @returns {string} + */ public getSamLocal(): string { return this.get(this.samLocalVariable); } + /** + * It returns the value of the POWERTOOLS_TRACER_CAPTURE_ERROR environment variable. + * + * @returns {string} + */ public getTracingCaptureError(): string { return this.get(this.tracerCaptureErrorVariable); } + /** + * It returns the value of the POWERTOOLS_TRACER_CAPTURE_RESPONSE environment variable. + * + * @returns {string} + */ public getTracingCaptureResponse(): string { return this.get(this.tracerCaptureResponseVariable); } + /** + * It returns the value of the POWERTOOLS_TRACE_ENABLED environment variable. + * + * @returns {string} + */ public getTracingEnabled(): string { return this.get(this.tracingEnabledVariable); } diff --git a/packages/tracer/src/middleware/middy.ts b/packages/tracer/src/middleware/middy.ts index fc208c1fef..16fd45676c 100644 --- a/packages/tracer/src/middleware/middy.ts +++ b/packages/tracer/src/middleware/middy.ts @@ -18,7 +18,8 @@ import type { * * @example * ```typescript - * import { Tracer, captureLambdaHandler } from '@aws-lambda-powertools/tracer'; + * import { Tracer } from '@aws-lambda-powertools/tracer'; + * import { captureLambdaHandler } from '@aws-lambda-powertools/tracer/middleware'; * import middy from '@middy/core'; * * const tracer = new Tracer({ serviceName: 'serverlessAirline' }); diff --git a/packages/tracer/src/provider/ProviderService.ts b/packages/tracer/src/provider/ProviderService.ts index 40130067b3..2194a8b8d9 100644 --- a/packages/tracer/src/provider/ProviderService.ts +++ b/packages/tracer/src/provider/ProviderService.ts @@ -3,7 +3,9 @@ import type { ProviderServiceInterface, ContextMissingStrategy, } from '../types/ProviderServiceInterface.js'; -import { +import type { Segment, Subsegment, Logger } from 'aws-xray-sdk-core'; +import xraySdk from 'aws-xray-sdk-core'; +const { captureAWS, captureAWSClient, captureAWSv3Client, @@ -13,13 +15,11 @@ import { getNamespace, getSegment, setSegment, - Segment, - Subsegment, + Segment: XraySegment, setContextMissingStrategy, setDaemonAddress, setLogger, - Logger, -} from 'aws-xray-sdk-core'; +} = xraySdk; import { addUserAgentMiddleware } from '@aws-lambda-powertools/commons'; class ProviderService implements ProviderServiceInterface { @@ -79,7 +79,7 @@ class ProviderService implements ProviderServiceInterface { return; } - if (segment instanceof Segment) { + if (segment instanceof XraySegment) { console.warn( 'You cannot annotate the main segment in a Lambda execution environment' ); @@ -98,7 +98,7 @@ class ProviderService implements ProviderServiceInterface { return; } - if (segment instanceof Segment) { + if (segment instanceof XraySegment) { console.warn( 'You cannot add metadata to the main segment in a Lambda execution environment' ); diff --git a/packages/tracer/src/types/ConfigServiceInterface.ts b/packages/tracer/src/types/ConfigServiceInterface.ts index 53b49febf9..8ac7b0bcd8 100644 --- a/packages/tracer/src/types/ConfigServiceInterface.ts +++ b/packages/tracer/src/types/ConfigServiceInterface.ts @@ -1,14 +1,53 @@ -interface ConfigServiceInterface { - get(name: string): string; +import type { ConfigServiceInterface as ConfigServiceBaseInterface } from '@aws-lambda-powertools/commons/types'; +/** + * Interface ConfigServiceInterface + * + * @interface + * @see https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime + * @see https://docs.powertools.aws.dev/lambda/typescript/latest/#environment-variables + */ +interface ConfigServiceInterface extends ConfigServiceBaseInterface { + /** + * It returns the value of the AWS_EXECUTION_ENV environment variable. + * + * @returns {string} + */ + getAwsExecutionEnv(): string; + + /** + * It returns the value of the POWERTOOLS_TRACER_CAPTURE_HTTPS_REQUESTS environment variable. + * + * @returns {string} + */ getCaptureHTTPsRequests(): string; - getTracingEnabled(): string; + /** + * It returns the value of the AWS_SAM_LOCAL environment variable. + * + * @returns {string} + */ + getSamLocal(): string; - getServiceName(): string; + /** + * It returns the value of the POWERTOOLS_TRACE_ENABLED environment variable. + * + * @returns {string} + */ + getTracingEnabled(): string; + /** + * It returns the value of the POWERTOOLS_TRACER_CAPTURE_RESPONSE environment variable. + * + * @returns {string} + */ getTracingCaptureResponse(): string; + /** + * It returns the value of the POWERTOOLS_TRACER_CAPTURE_ERROR environment variable. + * + * @returns {string} + */ getTracingCaptureError(): string; } diff --git a/packages/tracer/tests/e2e/constants.ts b/packages/tracer/tests/e2e/constants.ts index e6b5547c0b..907976c469 100644 --- a/packages/tracer/tests/e2e/constants.ts +++ b/packages/tracer/tests/e2e/constants.ts @@ -3,7 +3,7 @@ const RESOURCE_NAME_PREFIX = 'Tracer'; // Constants relating time to be used in the tests const ONE_MINUTE = 60 * 1_000; const TEST_CASE_TIMEOUT = 5 * ONE_MINUTE; -const SETUP_TIMEOUT = 5 * ONE_MINUTE; +const SETUP_TIMEOUT = 7 * ONE_MINUTE; const TEARDOWN_TIMEOUT = 5 * ONE_MINUTE; // Expected values for custom annotations, metadata, and response diff --git a/packages/tracer/tests/unit/Tracer.test.ts b/packages/tracer/tests/unit/Tracer.test.ts index 4b6031e092..04747e1f9f 100644 --- a/packages/tracer/tests/unit/Tracer.test.ts +++ b/packages/tracer/tests/unit/Tracer.test.ts @@ -139,6 +139,21 @@ describe('Class: Tracer', () => { getServiceName(): string { return 'my-backend-service'; }, + getSamLocal() { + return 'false'; + }, + getAwsExecutionEnv() { + return 'AWS_Lambda_nodejs12.x'; + }, + isDevMode(): boolean { + return false; + }, + isValueTrue(value: string): boolean { + return value === 'true'; + }, + getXrayTraceId() { + return '1-abcdef12-3456abcdef123456abcdef12'; + }, }; // Act diff --git a/tsconfig.json b/tsconfig.json index 0042e92513..c801ef543c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "incremental": true, "composite": true, - "target": "ES2022", // Node.js 16 + "target": "ES2021", // Node.js 16 "experimentalDecorators": true, "module": "commonjs", "moduleResolution": "node", From 17076b220b1b043928abe385200e3e438725fa0e Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Tue, 2 Apr 2024 14:21:22 +0200 Subject: [PATCH 12/23] merged package-lock --- package-lock.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 237963475e..8ce6b01514 100644 --- a/package-lock.json +++ b/package-lock.json @@ -66,7 +66,8 @@ "aws-sdk-client-mock": "^3.0.1", "aws-sdk-client-mock-jest": "^3.0.1", "axios": "^1.6.7", - "hashi-vault-js": "^0.4.14" + "hashi-vault-js": "^0.4.14", + "zod": "^3.22.4" } }, "examples/cdk": { @@ -17221,7 +17222,6 @@ "version": "3.22.4", "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } @@ -17367,6 +17367,7 @@ } }, "packages/parser": { + "name": "@aws-lambda-powertools/parser", "version": "0.0.0", "license": "MIT-0", "devDependencies": { From a4095f70d4c576941144e7fbc28ea782d9cba1ed Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Tue, 2 Apr 2024 15:38:02 +0200 Subject: [PATCH 13/23] Update docs/utilities/parser.md Co-authored-by: Andrea Amorosi --- docs/utilities/parser.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/utilities/parser.md b/docs/utilities/parser.md index 6ae6cd75c5..cc1671ea3d 100644 --- a/docs/utilities/parser.md +++ b/docs/utilities/parser.md @@ -15,7 +15,7 @@ Zod is a TypeScript-first schema declaration and validation library. * Define data schema as zod schema, then parse, validate and extract only what you want * Built-in envelopes to unwrap and validate popular event sources payloads * Extend and customize envelopes to fit your needs -* Available for middy middleware and TypeScript method decorators +* Available for Middy.js middleware and TypeScript method decorators ## Getting started From cb36ca535e4f9f8e9c8b0b33767b47a6314ba83f Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Tue, 2 Apr 2024 15:41:39 +0200 Subject: [PATCH 14/23] Update docs/utilities/parser.md Co-authored-by: Andrea Amorosi --- docs/utilities/parser.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/utilities/parser.md b/docs/utilities/parser.md index cc1671ea3d..0d7ef428b8 100644 --- a/docs/utilities/parser.md +++ b/docs/utilities/parser.md @@ -1,5 +1,5 @@ --- -title: Parser (zod) +title: Parser (Zod) descrition: Utility --- From 8bede3e6f71074b648cd274fde35ab3d5dbff95a Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Tue, 2 Apr 2024 16:29:08 +0200 Subject: [PATCH 15/23] adjust imports to new implementation --- docs/snippets/parser/decorator.ts | 20 +++++++++---------- docs/snippets/parser/envelopeDecorator.ts | 24 +++++++++++------------ docs/snippets/parser/envelopeMiddy.ts | 20 +++++++++---------- docs/snippets/parser/extend.ts | 18 ++++++++--------- docs/snippets/parser/manual.ts | 24 +++++++++++------------ docs/snippets/parser/middy.ts | 14 ++++++------- docs/snippets/parser/schema.ts | 16 +++++++-------- docs/snippets/parser/types.ts | 14 ++++++------- package-lock.json | 5 +++-- 9 files changed, 78 insertions(+), 77 deletions(-) diff --git a/docs/snippets/parser/decorator.ts b/docs/snippets/parser/decorator.ts index a8151d5f7a..f86615a5cf 100644 --- a/docs/snippets/parser/decorator.ts +++ b/docs/snippets/parser/decorator.ts @@ -1,24 +1,24 @@ -import { Context } from 'aws-lambda'; -import { LambdaInterface } from '@aws-lambda-powertools/commons'; +import type { Context } from 'aws-lambda'; +import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; import { parser } from '@aws-lambda-powertools/parser'; import { z } from 'zod'; -const orderItemSchema = z.object({ - id: z.number().positive(), - quantity: z.number(), - description: z.string(), -}); - const orderSchema = z.object({ id: z.number().positive(), description: z.string(), - items: z.array(orderItemSchema), + items: z.array( + z.object({ + id: z.number().positive(), + quantity: z.number(), + description: z.string(), + }) + ), optionalField: z.string().optional(), }); type Order = z.infer; -class Lambda extends LambdaInterface { +class Lambda implements LambdaInterface { @parser({ schema: orderSchema }) public async handler(event: Order, _context: Context): Promise { for (const item of event.items) { diff --git a/docs/snippets/parser/envelopeDecorator.ts b/docs/snippets/parser/envelopeDecorator.ts index 68845f68c5..c7bfadc433 100644 --- a/docs/snippets/parser/envelopeDecorator.ts +++ b/docs/snippets/parser/envelopeDecorator.ts @@ -1,26 +1,26 @@ -import { Context } from 'aws-lambda'; -import { LambdaInterface } from '@aws-lambda-powertools/commons'; +import type { Context } from 'aws-lambda'; +import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; import { parser } from '@aws-lambda-powertools/parser'; import { z } from 'zod'; -import { eventBridgeEnvelope } from '@aws-lambda-powertools/parser/envelopes'; - -const orderItemSchema = z.object({ - id: z.number().positive(), - quantity: z.number(), - description: z.string(), -}); +import { EventBridgeEnvelope } from '@aws-lambda-powertools/parser/envelopes'; const orderSchema = z.object({ id: z.number().positive(), description: z.string(), - items: z.array(orderItemSchema), + items: z.array( + z.object({ + id: z.number().positive(), + quantity: z.number(), + description: z.string(), + }) + ), optionalField: z.string().optional(), }); type Order = z.infer; -class Lambda extends LambdaInterface { - @parser({ schema: orderSchema, envelope: eventBridgeEnvelope }) // (1)! +class Lambda implements LambdaInterface { + @parser({ schema: orderSchema, envelope: EventBridgeEnvelope }) // (1)! public async handler(event: Order, _context: Context): Promise { for (const item of event.items) { // item is parsed as OrderItem diff --git a/docs/snippets/parser/envelopeMiddy.ts b/docs/snippets/parser/envelopeMiddy.ts index e56b3a8950..64d35ca43d 100644 --- a/docs/snippets/parser/envelopeMiddy.ts +++ b/docs/snippets/parser/envelopeMiddy.ts @@ -1,19 +1,19 @@ -import { Context } from 'aws-lambda'; +import type { Context } from 'aws-lambda'; import { parser } from '@aws-lambda-powertools/parser/middleware'; import { z } from 'zod'; import middy from '@middy/core'; -import { eventBridgeEnvelope } from '@aws-lambda-powertools/parser/envelopes'; - -const orderItemSchema = z.object({ - id: z.number().positive(), - quantity: z.number(), - description: z.string(), -}); +import { EventBridgeEnvelope } from '@aws-lambda-powertools/parser/envelopes'; const orderSchema = z.object({ id: z.number().positive(), description: z.string(), - items: z.array(orderItemSchema), + items: z.array( + z.object({ + id: z.number().positive(), + quantity: z.number(), + description: z.string(), + }) + ), optionalField: z.string().optional(), }); @@ -30,5 +30,5 @@ const lambdaHandler = async ( }; export const handler = middy(lambdaHandler).use( - parser({ schema: orderSchema, envelope: eventBridgeEnvelope }) + parser({ schema: orderSchema, envelope: EventBridgeEnvelope }) ); diff --git a/docs/snippets/parser/extend.ts b/docs/snippets/parser/extend.ts index e4d6da37d0..91c3472a3d 100644 --- a/docs/snippets/parser/extend.ts +++ b/docs/snippets/parser/extend.ts @@ -1,19 +1,19 @@ import { Context } from 'aws-lambda'; -import { LambdaInterface } from '@aws-lambda-powertools/commons'; +import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; import { parser } from '@aws-lambda-powertools/parser'; import { z } from 'zod'; import { EventBridgeSchema } from '@aws-lambda-powertools/parser/schemas'; -const orderItemSchema = z.object({ - id: z.number().positive(), - quantity: z.number(), - description: z.string(), -}); - const orderSchema = z.object({ id: z.number().positive(), description: z.string(), - items: z.array(orderItemSchema), + items: z.array( + z.object({ + id: z.number().positive(), + quantity: z.number(), + description: z.string(), + }) + ), optionalField: z.string().optional(), }); @@ -23,7 +23,7 @@ const orderEventSchema = EventBridgeSchema.extend({ type OrderEvent = z.infer; -class Lambda extends LambdaInterface { +class Lambda implements LambdaInterface { @parser({ schema: orderEventSchema }) // (2)! public async handler(event: OrderEvent, _context: Context): Promise { for (const item of event.detail.items) { diff --git a/docs/snippets/parser/manual.ts b/docs/snippets/parser/manual.ts index 9aba126018..de783c9156 100644 --- a/docs/snippets/parser/manual.ts +++ b/docs/snippets/parser/manual.ts @@ -1,30 +1,30 @@ -import { Context, EventBridgeEvent } from 'aws-lambda'; +import type { Context } from 'aws-lambda'; import { z } from 'zod'; -import { eventBridgeEnvelope } from '@aws-lambda-powertools/parser/envelopes'; +import { EventBridgeEnvelope } from '@aws-lambda-powertools/parser/envelopes'; import { EventBridgeSchema } from '@aws-lambda-powertools/parser/schemas'; - -const orderItemSchema = z.object({ - id: z.number().positive(), - quantity: z.number(), - description: z.string(), -}); +import type { EventBridgeEvent } from '@aws-lambda-powertools/parser/types'; const orderSchema = z.object({ id: z.number().positive(), description: z.string(), - items: z.array(orderItemSchema), + items: z.array( + z.object({ + id: z.number().positive(), + quantity: z.number(), + description: z.string(), + }) + ), optionalField: z.string().optional(), }); - type Order = z.infer; export const handler = async ( - event: EventBridgeEvent, + event: EventBridgeEvent, _context: Context ): Promise => { const parsedEvent = EventBridgeSchema.parse(event); // (1)! console.log(parsedEvent); - const orders: Order = eventBridgeEnvelope(event, orderSchema); // (2)! + const orders: Order = EventBridgeEnvelope.parse(event, orderSchema); // (2)! console.log(orders); }; diff --git a/docs/snippets/parser/middy.ts b/docs/snippets/parser/middy.ts index f95e3ac35f..59740faac9 100644 --- a/docs/snippets/parser/middy.ts +++ b/docs/snippets/parser/middy.ts @@ -3,16 +3,16 @@ import { parser } from '@aws-lambda-powertools/parser/middleware'; import { z } from 'zod'; import middy from '@middy/core'; -const orderItemSchema = z.object({ - id: z.number().positive(), - quantity: z.number(), - description: z.string(), -}); - const orderSchema = z.object({ id: z.number().positive(), description: z.string(), - items: z.array(orderItemSchema), + items: z.array( + z.object({ + id: z.number().positive(), + quantity: z.number(), + description: z.string(), + }) + ), optionalField: z.string().optional(), }); diff --git a/docs/snippets/parser/schema.ts b/docs/snippets/parser/schema.ts index 138e375239..f14db32fff 100644 --- a/docs/snippets/parser/schema.ts +++ b/docs/snippets/parser/schema.ts @@ -1,16 +1,16 @@ import { z } from 'zod'; -const orderItemSchema = z.object({ - id: z.number().positive(), - quantity: z.number(), - description: z.string(), -}); - const orderSchema = z.object({ id: z.number().positive(), description: z.string(), - items: z.array(orderItemSchema), + items: z.array( + z.object({ + id: z.number().positive(), + quantity: z.number(), + description: z.string(), + }) + ), optionalField: z.string().optional(), }); -export { orderSchema, orderItemSchema }; +export { orderSchema }; diff --git a/docs/snippets/parser/types.ts b/docs/snippets/parser/types.ts index 4f6ad1c675..26b32396cb 100644 --- a/docs/snippets/parser/types.ts +++ b/docs/snippets/parser/types.ts @@ -3,16 +3,16 @@ import { parser } from '@aws-lambda-powertools/parser/middleware'; import { z } from 'zod'; import middy from '@middy/core'; -const orderItemSchema = z.object({ - id: z.number().positive(), - quantity: z.number(), - description: z.string(), -}); - const orderSchema = z.object({ id: z.number().positive(), description: z.string(), - items: z.array(orderItemSchema), + items: z.array( + z.object({ + id: z.number().positive(), + quantity: z.number(), + description: z.string(), + }) + ), optionalField: z.string().optional(), }); diff --git a/package-lock.json b/package-lock.json index 5bd18ee54e..5807a254e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -66,7 +66,8 @@ "aws-sdk-client-mock": "^4.0.0", "aws-sdk-client-mock-jest": "^4.0.0", "axios": "^1.6.8", - "hashi-vault-js": "^0.4.14" + "hashi-vault-js": "^0.4.14", + "zod": "^3.22.4" } }, "examples/app": { @@ -17370,7 +17371,6 @@ "version": "3.22.4", "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } @@ -17523,6 +17523,7 @@ } }, "packages/parser": { + "name": "@aws-lambda-powertools/parser", "version": "0.0.0", "license": "MIT-0", "devDependencies": { From 0caf05afaf15ed7a7afa31670d5613bee6984c78 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Thu, 4 Apr 2024 11:03:11 +0200 Subject: [PATCH 16/23] add safeParse --- docs/snippets/package.json | 2 + docs/snippets/parser/decorator.ts | 2 +- docs/snippets/parser/envelopeDecorator.ts | 2 +- docs/snippets/parser/extend.ts | 2 +- docs/snippets/parser/manualSafeParse.ts | 33 ++++++++ docs/snippets/parser/middy.ts | 2 +- docs/snippets/parser/safeParseDecorator.ts | 44 +++++++++++ docs/snippets/parser/safeParseMiddy.ts | 42 +++++++++++ docs/snippets/parser/types.ts | 2 +- docs/snippets/tsconfig.json | 3 +- docs/utilities/parser.md | 88 ++++++++++++++++------ mkdocs.yml | 2 + package-lock.json | 1 + 13 files changed, 197 insertions(+), 28 deletions(-) create mode 100644 docs/snippets/parser/manualSafeParse.ts create mode 100644 docs/snippets/parser/safeParseDecorator.ts create mode 100644 docs/snippets/parser/safeParseMiddy.ts diff --git a/docs/snippets/package.json b/docs/snippets/package.json index 3de80bb5a6..ab6dc462c6 100644 --- a/docs/snippets/package.json +++ b/docs/snippets/package.json @@ -2,6 +2,7 @@ "name": "docs", "version": "2.0.3", "description": "A collection code snippets for the Powertools for AWS Lambda (TypeScript) docs", + "type": "module", "author": { "name": "Amazon Web Services", "url": "https://aws.amazon.com" @@ -33,6 +34,7 @@ "@aws-sdk/client-secrets-manager": "^3.543.0", "@aws-sdk/client-ssm": "^3.540.0", "@aws-sdk/util-dynamodb": "^3.540.0", + "@middy/core": "^4.7.0", "aws-sdk": "^2.1589.0", "aws-sdk-client-mock": "^4.0.0", "aws-sdk-client-mock-jest": "^4.0.0", diff --git a/docs/snippets/parser/decorator.ts b/docs/snippets/parser/decorator.ts index f86615a5cf..a24ad25979 100644 --- a/docs/snippets/parser/decorator.ts +++ b/docs/snippets/parser/decorator.ts @@ -21,8 +21,8 @@ type Order = z.infer; class Lambda implements LambdaInterface { @parser({ schema: orderSchema }) public async handler(event: Order, _context: Context): Promise { + // event is now typed as Order for (const item of event.items) { - // item is parsed as OrderItem console.log(item.id); } } diff --git a/docs/snippets/parser/envelopeDecorator.ts b/docs/snippets/parser/envelopeDecorator.ts index c7bfadc433..b7323f4c04 100644 --- a/docs/snippets/parser/envelopeDecorator.ts +++ b/docs/snippets/parser/envelopeDecorator.ts @@ -22,8 +22,8 @@ type Order = z.infer; class Lambda implements LambdaInterface { @parser({ schema: orderSchema, envelope: EventBridgeEnvelope }) // (1)! public async handler(event: Order, _context: Context): Promise { + // event is now typed as Order for (const item of event.items) { - // item is parsed as OrderItem console.log(item.id); // (2)! } } diff --git a/docs/snippets/parser/extend.ts b/docs/snippets/parser/extend.ts index 91c3472a3d..431e49fd42 100644 --- a/docs/snippets/parser/extend.ts +++ b/docs/snippets/parser/extend.ts @@ -1,4 +1,4 @@ -import { Context } from 'aws-lambda'; +import type { Context } from 'aws-lambda'; import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; import { parser } from '@aws-lambda-powertools/parser'; import { z } from 'zod'; diff --git a/docs/snippets/parser/manualSafeParse.ts b/docs/snippets/parser/manualSafeParse.ts new file mode 100644 index 0000000000..c2d68bdc4a --- /dev/null +++ b/docs/snippets/parser/manualSafeParse.ts @@ -0,0 +1,33 @@ +import type { Context } from 'aws-lambda'; +import { z } from 'zod'; +import { EventBridgeEnvelope } from '@aws-lambda-powertools/parser/envelopes'; +import { EventBridgeSchema } from '@aws-lambda-powertools/parser/schemas'; +import type { EventBridgeEvent } from '@aws-lambda-powertools/parser/types'; + +const orderSchema = z.object({ + id: z.number().positive(), + description: z.string(), + items: z.array( + z.object({ + id: z.number().positive(), + quantity: z.number(), + description: z.string(), + }) + ), + optionalField: z.string().optional(), +}); + +export const handler = async ( + event: EventBridgeEvent, + _context: Context +): Promise => { + const parsedEvent = EventBridgeSchema.safeParse(event); // (1)! + parsedEvent.success + ? console.log(parsedEvent.data) + : console.log(parsedEvent.error.message); + + const parsedEvenlope = EventBridgeEnvelope.safeParse(event, orderSchema); // (2)! + parsedEvenlope.success + ? console.log(parsedEvenlope.data) + : console.log(parsedEvenlope.error.message); +}; diff --git a/docs/snippets/parser/middy.ts b/docs/snippets/parser/middy.ts index 59740faac9..4e6abe747e 100644 --- a/docs/snippets/parser/middy.ts +++ b/docs/snippets/parser/middy.ts @@ -1,4 +1,4 @@ -import { Context } from 'aws-lambda'; +import type { Context } from 'aws-lambda'; import { parser } from '@aws-lambda-powertools/parser/middleware'; import { z } from 'zod'; import middy from '@middy/core'; diff --git a/docs/snippets/parser/safeParseDecorator.ts b/docs/snippets/parser/safeParseDecorator.ts new file mode 100644 index 0000000000..35aa0741cc --- /dev/null +++ b/docs/snippets/parser/safeParseDecorator.ts @@ -0,0 +1,44 @@ +import type { Context } from 'aws-lambda'; +import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; +import { parser } from '@aws-lambda-powertools/parser'; +import { z } from 'zod'; +import type { + ParsedResult, + EventBridgeEvent, +} from '@aws-lambda-powertools/parser/types'; + +const orderSchema = z.object({ + id: z.number().positive(), + description: z.string(), + items: z.array( + z.object({ + id: z.number().positive(), + quantity: z.number(), + description: z.string(), + }) + ), + optionalField: z.string().optional(), +}); + +type Order = z.infer; + +class Lambda implements LambdaInterface { + @parser({ schema: orderSchema, safeParse: true }) // (1)! + public async handler( + event: ParsedResult, + _context: Context + ): Promise { + if (event.success) { + // (2)! + for (const item of event.data.items) { + console.log(item.id); // (3)! + } + } else { + console.error(event.error); // (4)! + console.log(event.originalEvent); // (5)! + } + } +} + +const myFunction = new Lambda(); +export const handler = myFunction.handler.bind(myFunction); diff --git a/docs/snippets/parser/safeParseMiddy.ts b/docs/snippets/parser/safeParseMiddy.ts new file mode 100644 index 0000000000..86755685e3 --- /dev/null +++ b/docs/snippets/parser/safeParseMiddy.ts @@ -0,0 +1,42 @@ +import type { Context } from 'aws-lambda'; +import { parser } from '@aws-lambda-powertools/parser/middleware'; +import { z } from 'zod'; +import middy from '@middy/core'; +import type { + ParsedResult, + EventBridgeEvent, +} from '@aws-lambda-powertools/parser/types'; + +const orderSchema = z.object({ + id: z.number().positive(), + description: z.string(), + items: z.array( + z.object({ + id: z.number().positive(), + quantity: z.number(), + description: z.string(), + }) + ), + optionalField: z.string().optional(), +}); + +type Order = z.infer; + +const lambdaHandler = async ( + event: ParsedResult, + _context: Context +): Promise => { + if (event.success) { + // (2)! + for (const item of event.data.items) { + console.log(item.id); // (3)! + } + } else { + console.error(event.error); // (4)! + console.log(event.originalEvent); // (5)! + } +}; + +export const handler = middy(lambdaHandler).use( + parser({ schema: orderSchema, safeParse: true }) // (1)! +); diff --git a/docs/snippets/parser/types.ts b/docs/snippets/parser/types.ts index 26b32396cb..32ee5cd1c4 100644 --- a/docs/snippets/parser/types.ts +++ b/docs/snippets/parser/types.ts @@ -1,4 +1,4 @@ -import { Context } from 'aws-lambda'; +import type { Context } from 'aws-lambda'; import { parser } from '@aws-lambda-powertools/parser/middleware'; import { z } from 'zod'; import middy from '@middy/core'; diff --git a/docs/snippets/tsconfig.json b/docs/snippets/tsconfig.json index cebb64fd94..877951330e 100644 --- a/docs/snippets/tsconfig.json +++ b/docs/snippets/tsconfig.json @@ -33,7 +33,8 @@ "@aws-lambda-powertools/jmespath": ["../../packages/jmespath/lib"], "@aws-lambda-powertools/jmespath/envelopes": [ "../../packages/jmespath/lib/envelopes" - ] + ], + "@aws-lambda-powertools/parser": ["../../packages/parser/lib"] } } } diff --git a/docs/utilities/parser.md b/docs/utilities/parser.md index 0d7ef428b8..086e839dea 100644 --- a/docs/utilities/parser.md +++ b/docs/utilities/parser.md @@ -1,20 +1,22 @@ --- title: Parser (Zod) descrition: Utility +status: new --- ???+ warning **This utility is currently released as beta developer preview** and is intended strictly for feedback and testing purposes **and not for production workloads**. The version and all future versions tagged with the `-beta` suffix should be treated as not stable. Up until before the [General Availability release](https://github.com/aws-powertools/powertools-lambda-typescript/milestone/16) we might introduce significant breaking changes and improvements in response to customers feedback. -This utility provides data validation and parsing using [zod](https://zod.dev){target="_blank"}. +This utility provides data validation and parsing using [Zod](https://zod.dev){target="_blank"}. Zod is a TypeScript-first schema declaration and validation library. ## Key features -* Define data schema as zod schema, then parse, validate and extract only what you want -* Built-in envelopes to unwrap and validate popular event sources payloads +* Define data schema as Zod schema, then parse, validate and extract only what you want +* Built-in envelopes to unwrap and validate popular AWS event sources payloads * Extend and customize envelopes to fit your needs +* Safe parsing option to avoid throwing errors and custom error handling * Available for Middy.js middleware and TypeScript method decorators ## Getting started @@ -22,32 +24,33 @@ Zod is a TypeScript-first schema declaration and validation library. ### Install ```bash -npm install @aws-lambda-powertools/parser zod +npm install @aws-lambda-powertools/parser zod~3 ``` -This utility supports zod v3.0.0 and above. +This utility supports Zod v3.x and above. ## Define schema -You can define your schema using zod: +You can define your schema using Zod: ```typescript title="schema.ts" --8<-- "docs/snippets/parser/schema.ts" ``` -This is a schema for order and order items using zod. -You can create more complex schemas using zod, such as nested objects, arrays, unions, etc. see [zod documentation](https://zod.dev) for more details. +This is a schema for `Order` object using Zod. +You can create complex schemas by using nested objects, arrays, unions, and other types, see [Zod documentation](https://zod.dev) for more details. ## Parse events -You can parse inbound events using `parser` decorator or middy middleware. +You can parse inbound events using `parser` decorator or middy middleware, or [manually](#manual-parsing) using built-in envelopes and schemas. Both are also able to parse either an object or JSON string as an input. -???+ note - The decorator and middleware will replace the event object with the parsed schema if successful. This means you might be careful when nesting other decorators that expect event to have a specific structure. +???+ warning + The decorator and middleware will replace the event object with the parsed schema if successful. + Be careful when using multiple decorators that expect event to have a specific structure, the order of evaluation for decorators is from bottom to top. === "Middy middleware" - ```typescript hl_lines="31" + ```typescript hl_lines="32" --8<-- "docs/snippets/parser/middy.ts" ``` @@ -120,6 +123,11 @@ This can become difficult quite quickly. Parser simplifies the development throu Envelopes can be used via envelope parameter available in middy and decorator. Here's an example of parsing a custom schema in an event coming from EventBridge, where all you want is what's inside the detail key. +=== "Middy middleware" + ```typescript hl_lines="5 33" + --8<-- "docs/snippets/parser/envelopeMiddy.ts" + ``` + === "Decorator" ```typescript hl_lines="5 23" --8<-- "docs/snippets/parser/envelopeDecorator.ts" @@ -128,10 +136,7 @@ Here's an example of parsing a custom schema in an event coming from EventBridge 1. Pass `eventBridgeEnvelope` to `parser` decorator 2. `event` is parsed and replaced as `Order` object -=== "Middy middleware" - ```typescript hl_lines="5 32" - --8<-- "docs/snippets/parser/envelopeMiddy.ts" - ``` + The envelopes are functions that take an event and the schema to parse, and return the result of the inner schema. Depending on the envelope it can be something simple like extracting a key. @@ -163,22 +168,61 @@ Parser comes with the following built-in envelopes: | **vpcLatticeV2Envelope** | 1. Parses data using `VpcLatticeSchema`.
2. Parses `value` key using your schema and returns it. | +## Safe parsing + +If you want to parse the event without throwing an error, use the `safeParse` option. +The handler `event` object will be replaced with `ParsedResult`, for example `ParsedResult`, where `SqsEvent` is the original event and `Order` is the parsed schema. + +The `ParsedResult` object will have `success`, `data`, or `error` and `originalEvent` fields, depending on the outcome. +If the parsing is successful, the `data` field will contain the parsed event, otherwise you can access the `error` field and the `originalEvent` to handle the error and recover the original event. + +=== "Middy middleware" + ```typescript hl_lines="29 32 35 36 41" + --8<-- "docs/snippets/parser/safeParseMiddy.ts" + ``` + + 1. Use `safeParse` option to parse the event without throwing an error + 2. Check if the result is successful or not and handle the error accordingly + 3. Use `data` to access the parsed event + 4. Use `error` to handle the error message + 5. Use `originalEvent` to get the original event and recover + +=== "Decorator" + ```typescript hl_lines="26 31 34 37 38" + --8<-- "docs/snippets/parser/safeParseDecorator.ts" + ``` + + 1. Use `safeParse` option to parse the event without throwing an error + 2. Check if the result is successful or not and handle the error accordingly + 3. Use `data` to access the parsed event + 4. Use `error` to handle the error message + 5. Use `originalEvent` to get the original event and recover + + ## Manual parsing -You can use built-in envelopes and schemas to parse the incoming events manually: +You can use built-in envelopes and schemas to parse the incoming events manually, without using middy or decorator. + -=== "Manual parsing" +=== "Manual parse" ```typescript hl_lines="25 28" --8<-- "docs/snippets/parser/manual.ts" ``` - + 1. Use `EventBridgeSchema` to parse the event, the `details` fields will be parsed as a generic record. 2. Use `eventBridgeEnvelope` with a combination of `orderSchema` to get `Order` object from the `details` field. +=== "Manual safeParse" + ```typescript hl_lines="24 29" + --8<-- "docs/snippets/parser/manualSafeParse.ts" + ``` + + 1. Use `safeParse` option to parse the event without throwing an error + 2. `safeParse` is also available for envelopes ## Custom validation -Because Parser uses zod, you can use all the features of zod to validate your data. +Because Parser uses Zod, you can use all the features of Zod to validate your data. For example, you can use `refine` to validate a field or a combination of fields: === "Custom validation" @@ -186,7 +230,7 @@ For example, you can use `refine` to validate a field or a combination of fields --8<-- "docs/snippets/parser/refine.ts" ``` -Zod provides a lot of other features and customization, see [zod documentation](https://zod.dev) for more details. +Zod provides a lot of other features and customization, see [Zod documentation](https://zod.dev) for more details. ## Types @@ -213,4 +257,4 @@ We are working on a sustainable solution to make them compatible and avoid any b We recommend to use the types provided by the parser utility. ## Error handling -We don't have any error handling in the utility and propagate all errors from zod, which are thrown as `ZodError`. +We don't have any error handling in the utility and propagate all errors from Zod, which are thrown as `ZodError`. diff --git a/mkdocs.yml b/mkdocs.yml index 7410905084..31e1be3d24 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -120,3 +120,5 @@ extra: - icon: fontawesome/brands/discord link: https://discord.gg/B8zZKbbyET name: Join our Discord Server! + status: + new: New Utility diff --git a/package-lock.json b/package-lock.json index 5807a254e7..f726c5f6ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -62,6 +62,7 @@ "@aws-sdk/client-secrets-manager": "^3.543.0", "@aws-sdk/client-ssm": "^3.540.0", "@aws-sdk/util-dynamodb": "^3.540.0", + "@middy/core": "^4.7.0", "aws-sdk": "^2.1589.0", "aws-sdk-client-mock": "^4.0.0", "aws-sdk-client-mock-jest": "^4.0.0", From 55aeb063365bbfc085f2a6e9956b7cbeaa061be3 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Thu, 4 Apr 2024 15:38:57 +0200 Subject: [PATCH 17/23] fixed line highlight --- docs/snippets/parser/decorator.ts | 5 ++- docs/snippets/parser/envelopeDecorator.ts | 5 ++- docs/snippets/parser/envelopeMiddy.ts | 5 ++- docs/snippets/parser/extend.ts | 5 ++- docs/snippets/parser/manual.ts | 7 +++- docs/snippets/parser/manualSafeParse.ts | 12 +++--- docs/snippets/parser/middy.ts | 5 ++- docs/snippets/parser/refine.ts | 4 +- docs/snippets/parser/safeParseDecorator.ts | 9 +++-- docs/snippets/parser/safeParseMiddy.ts | 9 +++-- docs/snippets/parser/types.ts | 5 ++- docs/snippets/tsconfig.json | 3 +- docs/utilities/parser.md | 44 +++++++++++----------- 13 files changed, 73 insertions(+), 45 deletions(-) diff --git a/docs/snippets/parser/decorator.ts b/docs/snippets/parser/decorator.ts index a24ad25979..c1a91ad096 100644 --- a/docs/snippets/parser/decorator.ts +++ b/docs/snippets/parser/decorator.ts @@ -2,6 +2,9 @@ import type { Context } from 'aws-lambda'; import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; import { parser } from '@aws-lambda-powertools/parser'; import { z } from 'zod'; +import { Logger } from '@aws-lambda-powertools/logger'; + +const logger = new Logger(); const orderSchema = z.object({ id: z.number().positive(), @@ -23,7 +26,7 @@ class Lambda implements LambdaInterface { public async handler(event: Order, _context: Context): Promise { // event is now typed as Order for (const item of event.items) { - console.log(item.id); + logger.info('Processing item', { item }); } } } diff --git a/docs/snippets/parser/envelopeDecorator.ts b/docs/snippets/parser/envelopeDecorator.ts index b7323f4c04..e54e0f7387 100644 --- a/docs/snippets/parser/envelopeDecorator.ts +++ b/docs/snippets/parser/envelopeDecorator.ts @@ -3,6 +3,9 @@ import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; import { parser } from '@aws-lambda-powertools/parser'; import { z } from 'zod'; import { EventBridgeEnvelope } from '@aws-lambda-powertools/parser/envelopes'; +import { Logger } from '@aws-lambda-powertools/logger'; + +const logger = new Logger(); const orderSchema = z.object({ id: z.number().positive(), @@ -24,7 +27,7 @@ class Lambda implements LambdaInterface { public async handler(event: Order, _context: Context): Promise { // event is now typed as Order for (const item of event.items) { - console.log(item.id); // (2)! + logger.info('Processing item', item); // (2)! } } } diff --git a/docs/snippets/parser/envelopeMiddy.ts b/docs/snippets/parser/envelopeMiddy.ts index 64d35ca43d..94f8f012af 100644 --- a/docs/snippets/parser/envelopeMiddy.ts +++ b/docs/snippets/parser/envelopeMiddy.ts @@ -3,6 +3,9 @@ import { parser } from '@aws-lambda-powertools/parser/middleware'; import { z } from 'zod'; import middy from '@middy/core'; import { EventBridgeEnvelope } from '@aws-lambda-powertools/parser/envelopes'; +import { Logger } from '@aws-lambda-powertools/logger'; + +const logger = new Logger(); const orderSchema = z.object({ id: z.number().positive(), @@ -25,7 +28,7 @@ const lambdaHandler = async ( ): Promise => { for (const item of event.items) { // item is parsed as OrderItem - console.log(item.id); + logger.info('Processing item', { item }); } }; diff --git a/docs/snippets/parser/extend.ts b/docs/snippets/parser/extend.ts index 431e49fd42..d14845c10f 100644 --- a/docs/snippets/parser/extend.ts +++ b/docs/snippets/parser/extend.ts @@ -3,6 +3,9 @@ import type { LambdaInterface } from '@aws-lambda-powertools/commons/types'; import { parser } from '@aws-lambda-powertools/parser'; import { z } from 'zod'; import { EventBridgeSchema } from '@aws-lambda-powertools/parser/schemas'; +import { Logger } from '@aws-lambda-powertools/logger'; + +const logger = new Logger(); const orderSchema = z.object({ id: z.number().positive(), @@ -28,7 +31,7 @@ class Lambda implements LambdaInterface { public async handler(event: OrderEvent, _context: Context): Promise { for (const item of event.detail.items) { // process OrderItem - console.log(item); // (3)! + logger.info('Processing item', { item }); // (3)! } } } diff --git a/docs/snippets/parser/manual.ts b/docs/snippets/parser/manual.ts index de783c9156..2be8204cad 100644 --- a/docs/snippets/parser/manual.ts +++ b/docs/snippets/parser/manual.ts @@ -3,6 +3,9 @@ import { z } from 'zod'; import { EventBridgeEnvelope } from '@aws-lambda-powertools/parser/envelopes'; import { EventBridgeSchema } from '@aws-lambda-powertools/parser/schemas'; import type { EventBridgeEvent } from '@aws-lambda-powertools/parser/types'; +import { Logger } from '@aws-lambda-powertools/logger'; + +const logger = new Logger(); const orderSchema = z.object({ id: z.number().positive(), @@ -23,8 +26,8 @@ export const handler = async ( _context: Context ): Promise => { const parsedEvent = EventBridgeSchema.parse(event); // (1)! - console.log(parsedEvent); + logger.info('Parsed event', parsedEvent); const orders: Order = EventBridgeEnvelope.parse(event, orderSchema); // (2)! - console.log(orders); + logger.info('Parsed orders', orders); }; diff --git a/docs/snippets/parser/manualSafeParse.ts b/docs/snippets/parser/manualSafeParse.ts index c2d68bdc4a..17106c1bda 100644 --- a/docs/snippets/parser/manualSafeParse.ts +++ b/docs/snippets/parser/manualSafeParse.ts @@ -3,6 +3,9 @@ import { z } from 'zod'; import { EventBridgeEnvelope } from '@aws-lambda-powertools/parser/envelopes'; import { EventBridgeSchema } from '@aws-lambda-powertools/parser/schemas'; import type { EventBridgeEvent } from '@aws-lambda-powertools/parser/types'; +import { Logger } from '@aws-lambda-powertools/logger'; + +const logger = new Logger(); const orderSchema = z.object({ id: z.number().positive(), @@ -23,11 +26,10 @@ export const handler = async ( ): Promise => { const parsedEvent = EventBridgeSchema.safeParse(event); // (1)! parsedEvent.success - ? console.log(parsedEvent.data) - : console.log(parsedEvent.error.message); - + ? logger.info('Event parsed successfully', parsedEvent.data) + : logger.error('Event parsing failed', parsedEvent.error); const parsedEvenlope = EventBridgeEnvelope.safeParse(event, orderSchema); // (2)! parsedEvenlope.success - ? console.log(parsedEvenlope.data) - : console.log(parsedEvenlope.error.message); + ? logger.info('Event envelope parsed successfully', parsedEvenlope.data) + : logger.error('Event envelope parsing failed', parsedEvenlope.error); }; diff --git a/docs/snippets/parser/middy.ts b/docs/snippets/parser/middy.ts index 4e6abe747e..ff3bf3a879 100644 --- a/docs/snippets/parser/middy.ts +++ b/docs/snippets/parser/middy.ts @@ -2,6 +2,9 @@ import type { Context } from 'aws-lambda'; import { parser } from '@aws-lambda-powertools/parser/middleware'; import { z } from 'zod'; import middy from '@middy/core'; +import { Logger } from '@aws-lambda-powertools/logger'; + +const logger = new Logger(); const orderSchema = z.object({ id: z.number().positive(), @@ -24,7 +27,7 @@ const lambdaHandler = async ( ): Promise => { for (const item of event.items) { // item is parsed as OrderItem - console.log(item.id); + logger.info('Processing item', { item }); } }; diff --git a/docs/snippets/parser/refine.ts b/docs/snippets/parser/refine.ts index 4a701240e8..b3e58fad08 100644 --- a/docs/snippets/parser/refine.ts +++ b/docs/snippets/parser/refine.ts @@ -11,11 +11,11 @@ export const orderSchema = z id: z.number().positive(), description: z.string(), items: z.array(orderItemSchema).refine((items) => items.length > 0, { - message: 'Order must have at least one item', + message: 'Order must have at least one item', // (1)! }), optionalField: z.string().optional(), }) .refine((order) => order.id > 100 && order.items.length > 100, { message: - 'All orders with more than 100 items must have an id greater than 100', + 'All orders with more than 100 items must have an id greater than 100', // (2)! }); diff --git a/docs/snippets/parser/safeParseDecorator.ts b/docs/snippets/parser/safeParseDecorator.ts index 35aa0741cc..aaf4d19ca9 100644 --- a/docs/snippets/parser/safeParseDecorator.ts +++ b/docs/snippets/parser/safeParseDecorator.ts @@ -6,6 +6,9 @@ import type { ParsedResult, EventBridgeEvent, } from '@aws-lambda-powertools/parser/types'; +import { Logger } from '@aws-lambda-powertools/logger'; + +const logger = new Logger(); const orderSchema = z.object({ id: z.number().positive(), @@ -31,11 +34,11 @@ class Lambda implements LambdaInterface { if (event.success) { // (2)! for (const item of event.data.items) { - console.log(item.id); // (3)! + logger.info('Processing item', { item }); // (3)! } } else { - console.error(event.error); // (4)! - console.log(event.originalEvent); // (5)! + logger.error('Failed to parse event', event.error); // (4)! + logger.error('Original event is: ', event.originalEvent); // (5)! } } } diff --git a/docs/snippets/parser/safeParseMiddy.ts b/docs/snippets/parser/safeParseMiddy.ts index 86755685e3..547eae73b7 100644 --- a/docs/snippets/parser/safeParseMiddy.ts +++ b/docs/snippets/parser/safeParseMiddy.ts @@ -6,6 +6,9 @@ import type { ParsedResult, EventBridgeEvent, } from '@aws-lambda-powertools/parser/types'; +import { Logger } from '@aws-lambda-powertools/logger'; + +const logger = new Logger(); const orderSchema = z.object({ id: z.number().positive(), @@ -29,11 +32,11 @@ const lambdaHandler = async ( if (event.success) { // (2)! for (const item of event.data.items) { - console.log(item.id); // (3)! + logger.info('Processing item', { item }); // (3)! } } else { - console.error(event.error); // (4)! - console.log(event.originalEvent); // (5)! + logger.error('Error parsing event', { event: event.error }); // (4)! + logger.error('Original event', { event: event.originalEvent }); // (5)! } }; diff --git a/docs/snippets/parser/types.ts b/docs/snippets/parser/types.ts index 32ee5cd1c4..eba3862835 100644 --- a/docs/snippets/parser/types.ts +++ b/docs/snippets/parser/types.ts @@ -2,6 +2,9 @@ import type { Context } from 'aws-lambda'; import { parser } from '@aws-lambda-powertools/parser/middleware'; import { z } from 'zod'; import middy from '@middy/core'; +import { Logger } from '@aws-lambda-powertools/logger'; + +const logger = new Logger(); const orderSchema = z.object({ id: z.number().positive(), @@ -24,7 +27,7 @@ const lambdaHandler = async ( ): Promise => { for (const item of event.items) { // item is parsed as OrderItem - console.log(item.id); // (3)! + logger.info('Processing item', { item }); // (3)! } }; diff --git a/docs/snippets/tsconfig.json b/docs/snippets/tsconfig.json index 877951330e..7c921276c8 100644 --- a/docs/snippets/tsconfig.json +++ b/docs/snippets/tsconfig.json @@ -34,7 +34,8 @@ "@aws-lambda-powertools/jmespath/envelopes": [ "../../packages/jmespath/lib/envelopes" ], - "@aws-lambda-powertools/parser": ["../../packages/parser/lib"] + "@aws-lambda-powertools/parser": ["../../packages/parser/lib"], + "@aws-lambda-powertools/logger": ["../../packages/logger/lib"] } } } diff --git a/docs/utilities/parser.md b/docs/utilities/parser.md index 086e839dea..615dbef9c3 100644 --- a/docs/utilities/parser.md +++ b/docs/utilities/parser.md @@ -47,15 +47,15 @@ Both are also able to parse either an object or JSON string as an input. ???+ warning The decorator and middleware will replace the event object with the parsed schema if successful. - Be careful when using multiple decorators that expect event to have a specific structure, the order of evaluation for decorators is from bottom to top. + Be cautious when using multiple decorators that expect event to have a specific structure, the order of evaluation for decorators is from bottom to top. === "Middy middleware" - ```typescript hl_lines="32" + ```typescript hl_lines="34" --8<-- "docs/snippets/parser/middy.ts" ``` === "Decorator" - ```typescript hl_lines="22" + ```typescript hl_lines="25" --8<-- "docs/snippets/parser/decorator.ts" ``` @@ -96,7 +96,7 @@ Parser comes with the following built-in schemas: You can extend every built-in schema to include your own schema, and yet have all other known fields parsed along the way. === "handler.ts" - ```typescript hl_lines="20-22 27 30" + ```typescript hl_lines="23-25 30 34" --8<-- "docs/snippets/parser/extend.ts" ``` @@ -124,12 +124,12 @@ Envelopes can be used via envelope parameter available in middy and decorator. Here's an example of parsing a custom schema in an event coming from EventBridge, where all you want is what's inside the detail key. === "Middy middleware" - ```typescript hl_lines="5 33" + ```typescript hl_lines="5 36" --8<-- "docs/snippets/parser/envelopeMiddy.ts" ``` === "Decorator" - ```typescript hl_lines="5 23" + ```typescript hl_lines="5 26 30" --8<-- "docs/snippets/parser/envelopeDecorator.ts" ``` @@ -177,7 +177,7 @@ The `ParsedResult` object will have `success`, `data`, or `error` and `original If the parsing is successful, the `data` field will contain the parsed event, otherwise you can access the `error` field and the `originalEvent` to handle the error and recover the original event. === "Middy middleware" - ```typescript hl_lines="29 32 35 36 41" + ```typescript hl_lines="32 35 38 39 44" --8<-- "docs/snippets/parser/safeParseMiddy.ts" ``` @@ -188,7 +188,7 @@ If the parsing is successful, the `data` field will contain the parsed event, ot 5. Use `originalEvent` to get the original event and recover === "Decorator" - ```typescript hl_lines="26 31 34 37 38" + ```typescript hl_lines="29 35 37 40 41" --8<-- "docs/snippets/parser/safeParseDecorator.ts" ``` @@ -205,7 +205,7 @@ You can use built-in envelopes and schemas to parse the incoming events manually === "Manual parse" - ```typescript hl_lines="25 28" + ```typescript hl_lines="28 31" --8<-- "docs/snippets/parser/manual.ts" ``` @@ -213,7 +213,7 @@ You can use built-in envelopes and schemas to parse the incoming events manually 2. Use `eventBridgeEnvelope` with a combination of `orderSchema` to get `Order` object from the `details` field. === "Manual safeParse" - ```typescript hl_lines="24 29" + ```typescript hl_lines="27 31" --8<-- "docs/snippets/parser/manualSafeParse.ts" ``` @@ -230,31 +230,29 @@ For example, you can use `refine` to validate a field or a combination of fields --8<-- "docs/snippets/parser/refine.ts" ``` + 1. validate a single field + 2. validate an object with multiple fields + Zod provides a lot of other features and customization, see [Zod documentation](https://zod.dev) for more details. ## Types ### Schema and Type inference -Zod provides a way to extract the type of schema, so you can use it in your handler: +Use `z.infer` to extract the type of the schema, so you can use types during development and avoid type errors. === "Types" - ```typescript hl_lines="19 22 27" + ```typescript hl_lines="22 25 30" --8<-- "docs/snippets/parser/types.ts" ``` - 1. Use `z.infer` to extract the type of the schema - 2. `event` is typed as `Order` object - 3. we can infer deeply nested types, here `Order` and `OrderItem` are inferred + 1. Use `z.infer` to extract the type of the schema, also works for nested schemas + 2. `event` is of type `Order` + 3. infer types from deeply nested schemas ### Compatibility with @types/aws-lambda -The package `@types/aws-lambda` contains type definitions for AWS service event invocations. -Powertools parser utility also bring AWS Lambda event types based on the built-in schema definitions. -Both libraries try to provide types for the same event structure, but they might not be compatible with each other yet. -We are working on a sustainable solution to make them compatible and avoid any breaking changes in the future. - -We recommend to use the types provided by the parser utility. +The package `@types/aws-lambda` is a popular project that contains type definitions for many AWS service event invocations. +Powertools parser utility also bring AWS Lambda event types based on the built-in schema definitions. -## Error handling -We don't have any error handling in the utility and propagate all errors from Zod, which are thrown as `ZodError`. +We recommend to use the types provided by the parser utilit. If you encounter any issues or have any feedback, please [submit an issue](https://github.com/aws-powertools/powertools-lambda-typescript/issues/new/choose). From 664a12e4022b219a447d400ba81c5efdec30f723 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Thu, 4 Apr 2024 15:40:28 +0200 Subject: [PATCH 18/23] typo --- docs/utilities/parser.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/utilities/parser.md b/docs/utilities/parser.md index 615dbef9c3..bbedb0de72 100644 --- a/docs/utilities/parser.md +++ b/docs/utilities/parser.md @@ -255,4 +255,4 @@ Use `z.infer` to extract the type of the schema, so you can use types during dev The package `@types/aws-lambda` is a popular project that contains type definitions for many AWS service event invocations. Powertools parser utility also bring AWS Lambda event types based on the built-in schema definitions. -We recommend to use the types provided by the parser utilit. If you encounter any issues or have any feedback, please [submit an issue](https://github.com/aws-powertools/powertools-lambda-typescript/issues/new/choose). +We recommend to use the types provided by the parser utility. If you encounter any issues or have any feedback, please [submit an issue](https://github.com/aws-powertools/powertools-lambda-typescript/issues/new/choose). From ef474591e583c4afb62d329c9c793f25bcf69eb4 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Thu, 4 Apr 2024 15:57:10 +0200 Subject: [PATCH 19/23] revert index.md, add private scope to snippets packagef --- docs/index.md | 14 +++++++------- docs/snippets/package.json | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/index.md b/docs/index.md index b12b644816..0e885f1921 100644 --- a/docs/index.md +++ b/docs/index.md @@ -8,7 +8,7 @@ Powertools for AWS Lambda (TypeScript) is a developer toolkit to implement Serve You can use Powertools for AWS Lambda (TypeScript) in both TypeScript and JavaScript code bases. ???+ tip - Powertools for AWS Lambda is also available for [Python](https://docs.powertools.aws.dev/lambda/python/){target="_blank"}, [Java](https://docs.powertools.aws.dev/lambda/java/){target="_blank"}, and [.NET](https://docs.powertools.aws.dev/lambda/dotnet/){target="_blank"} +Powertools for AWS Lambda is also available for [Python](https://docs.powertools.aws.dev/lambda/python/){target="_blank"}, [Java](https://docs.powertools.aws.dev/lambda/java/){target="_blank"}, and [.NET](https://docs.powertools.aws.dev/lambda/dotnet/){target="_blank"} ??? hint "Support this project by becoming a reference customer, sharing your work, or using Layers :heart:" @@ -26,7 +26,7 @@ You can use Powertools for AWS Lambda (TypeScript) in both TypeScript and JavaSc You can install Powertools for AWS Lambda (TypeScript) using one of the following options: -* **Lambda Layer**: [**arn:aws:lambda:{region}:094274105915:layer:AWSLambdaPowertoolsTypeScript:21**](#){: .copyMe}:clipboard: +* **Lambda Layer**: [**arn:aws:lambda:{region}:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:3**](#){: .copyMe}:clipboard: * **npm**: [`npm install @aws-lambda-powertools/tracer @aws-lambda-powertools/metrics @aws-lambda-powertools/logger`](#){: .copyMe}:clipboard: ### Lambda Layer @@ -70,7 +70,7 @@ You can include Powertools for AWS Lambda (TypeScript) Lambda Layer using [AWS L | `il-central-1` | [arn:aws:lambda:il-central-1:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:3](#){: .copyMe}:clipboard: | ??? note "Click to expand and copy code snippets for popular frameworks" - + === "SAM" ```yaml hl_lines="5" @@ -252,7 +252,7 @@ You can include Powertools for AWS Lambda (TypeScript) Lambda Layer using [AWS L !!! info "Using Powertools for AWS Lambda (TypeScript) via Lambda Layer? Simply add the Powertools for AWS Lambda (TypeScript) utilities you are using as a development dependency" ??? question "Want to inspect the contents of the Layer?" - Change {region} to your AWS region, e.g. `eu-west-1` +Change {region} to your AWS region, e.g. `eu-west-1` ```bash title="AWS CLI" aws lambda get-layer-version-by-arn --arn arn:aws:lambda:{aws::region}:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:3 --region {region} @@ -262,7 +262,7 @@ You can include Powertools for AWS Lambda (TypeScript) Lambda Layer using [AWS L ## Instrumentation -You can instrument your code with Powertools for AWS Lambda (TypeScript) in three different ways: +You can instrument your code with Powertools for AWS Lambda (TypeScript) in three different ways: * **Middy** middleware. It is the best choice if your existing code base relies on the [Middy 4.x](https://middy.js.org/docs/) middleware engine. Powertools for AWS Lambda (TypeScript) offers compatible Middy middleware to make this integration seamless. * **Method decorator**. Use [TypeScript method decorators](https://www.typescriptlang.org/docs/handbook/decorators.html#method-decorators) if you prefer writing your business logic using [TypeScript Classes](https://www.typescriptlang.org/docs/handbook/classes.html). If you aren’t using Classes, this requires the most significant refactoring. @@ -293,7 +293,7 @@ Core utilities such as Tracing, Logging, and Metrics will be available across al ## Environment variables ???+ info - Explicit parameters take precedence over environment variables +Explicit parameters take precedence over environment variables | Environment variable | Description | Utility | Default | | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | --------------------------------------- | ------------------- | @@ -351,4 +351,4 @@ These are our core principles to guide our decision making. * **We strive for backwards compatibility**. New features and changes should keep backwards compatibility. If a breaking change cannot be avoided, the deprecation and migration process should be clearly defined. * **We work backwards from the community**. We aim to strike a balance of what would work best for 80% of customers. Emerging practices are considered and discussed via Requests for Comment (RFCs) * **Progressive**. Utilities are designed to be incrementally adoptable for customers at any stage of their Serverless journey. They follow language idioms and their community’s common practices. - + \ No newline at end of file diff --git a/docs/snippets/package.json b/docs/snippets/package.json index ab6dc462c6..16b9b8aada 100644 --- a/docs/snippets/package.json +++ b/docs/snippets/package.json @@ -7,6 +7,7 @@ "name": "Amazon Web Services", "url": "https://aws.amazon.com" }, + "private": true, "scripts": { "test": "echo 'Not Applicable'", "test:e2e": "echo 'Not Applicable'", From 12ca395c1f38f5b3f6466be4584cbb8559ab788c Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Thu, 4 Apr 2024 15:57:57 +0200 Subject: [PATCH 20/23] Update docs/utilities/parser.md Co-authored-by: Andrea Amorosi --- docs/utilities/parser.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/utilities/parser.md b/docs/utilities/parser.md index bbedb0de72..7a31119c29 100644 --- a/docs/utilities/parser.md +++ b/docs/utilities/parser.md @@ -24,7 +24,7 @@ Zod is a TypeScript-first schema declaration and validation library. ### Install ```bash -npm install @aws-lambda-powertools/parser zod~3 +npm install @aws-lambda-powertools/parser zod@~3 ``` This utility supports Zod v3.x and above. From 115a6128009e834da1bc9d0e8fbb7f9542f74c35 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Fri, 5 Apr 2024 09:11:24 +0200 Subject: [PATCH 21/23] add parser to main, fixed zod install command --- docs/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/index.md b/docs/index.md index 0e885f1921..ac29e8b0e0 100644 --- a/docs/index.md +++ b/docs/index.md @@ -289,6 +289,7 @@ Core utilities such as Tracing, Logging, and Metrics will be available across al | [Parameters](./utilities/parameters.md) | High-level functions to retrieve one or more parameters from AWS SSM Parameter Store, AWS Secrets Manager, AWS AppConfig, and Amazon DynamoDB | | [Idempotency](./utilities/idempotency.md) | Class method decorator, Middy middleware, and function wrapper to make your Lambda functions idempotent and prevent duplicate execution based on payload content. | | [Batch Processing](./utilities/batch.md) | Utility to handle partial failures when processing batches from Amazon SQS, Amazon Kinesis Data Streams, and Amazon DynamoDB Streams. | +| [Parser](./utilities/parser.md) | Utility to parse and validate AWS Lambda event payloads using Zod, a TypeScript-first schema declaration and validation library. | ## Environment variables From ad1630417baa01950c4ddb194ae52e89e1c36aec Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Fri, 5 Apr 2024 09:45:28 +0200 Subject: [PATCH 22/23] fix callout indent --- docs/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/index.md b/docs/index.md index ac29e8b0e0..69b49012fa 100644 --- a/docs/index.md +++ b/docs/index.md @@ -8,7 +8,7 @@ Powertools for AWS Lambda (TypeScript) is a developer toolkit to implement Serve You can use Powertools for AWS Lambda (TypeScript) in both TypeScript and JavaScript code bases. ???+ tip -Powertools for AWS Lambda is also available for [Python](https://docs.powertools.aws.dev/lambda/python/){target="_blank"}, [Java](https://docs.powertools.aws.dev/lambda/java/){target="_blank"}, and [.NET](https://docs.powertools.aws.dev/lambda/dotnet/){target="_blank"} + Powertools for AWS Lambda is also available for [Python](https://docs.powertools.aws.dev/lambda/python/){target="_blank"}, [Java](https://docs.powertools.aws.dev/lambda/java/){target="_blank"}, and [.NET](https://docs.powertools.aws.dev/lambda/dotnet/){target="_blank"} ??? hint "Support this project by becoming a reference customer, sharing your work, or using Layers :heart:" @@ -252,7 +252,7 @@ You can include Powertools for AWS Lambda (TypeScript) Lambda Layer using [AWS L !!! info "Using Powertools for AWS Lambda (TypeScript) via Lambda Layer? Simply add the Powertools for AWS Lambda (TypeScript) utilities you are using as a development dependency" ??? question "Want to inspect the contents of the Layer?" -Change {region} to your AWS region, e.g. `eu-west-1` + Change {region} to your AWS region, e.g. `eu-west-1` ```bash title="AWS CLI" aws lambda get-layer-version-by-arn --arn arn:aws:lambda:{aws::region}:094274105915:layer:AWSLambdaPowertoolsTypeScriptV2:3 --region {region} From 40ac07103cee06c08c489a4666dee341732a94e6 Mon Sep 17 00:00:00 2001 From: Alexander Schueren Date: Fri, 5 Apr 2024 13:04:16 +0200 Subject: [PATCH 23/23] fix tooltip --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index 69b49012fa..ed1c1e514b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -294,7 +294,7 @@ Core utilities such as Tracing, Logging, and Metrics will be available across al ## Environment variables ???+ info -Explicit parameters take precedence over environment variables + Explicit parameters take precedence over environment variables | Environment variable | Description | Utility | Default | | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | --------------------------------------- | ------------------- |