diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 5dad4a2..0000000 --- a/.editorconfig +++ /dev/null @@ -1,27 +0,0 @@ -# http://editorconfig.org - -root = true - -[*] -indent_style = space -indent_size = 4 -trim_trailing_whitespace = true -insert_final_newline = true -charset = utf-8 -end_of_line = lf - -[*.{yaml,yml}] -indent_size = 2 - -[*.{ts,js}] -indent_size = 2 - -[*.bat] -indent_style = tab -end_of_line = crlf - -[LICENSE] -insert_final_newline = false - -[Makefile] -indent_style = tab diff --git a/.github/workflows/github-ip-ranges.yaml b/.github/workflows/github-ip-ranges.yaml index 0e8f0c9..f4ce74a 100644 --- a/.github/workflows/github-ip-ranges.yaml +++ b/.github/workflows/github-ip-ranges.yaml @@ -51,7 +51,7 @@ jobs: uses: ExpediaGroup/github-helpers@v1 with: helper: create-pr - title: 'fix: update Github IP ranges' + title: "fix: update Github IP ranges" body: The GitHub IP ranges for hooks have changed on the [meta endpoint](https://api.github.com/meta). head: github-ip-range-update github_token: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }} diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 91701c2..3e06929 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -13,16 +13,14 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version-file: .nvmrc + - name: Setup Bun + uses: oven-sh/setup-bun@v1 - name: Install - run: npm ci + run: bun i - name: Build - run: npm run build + run: bun run build - name: Inject Mozilla Cert Bundles run: curl https://curl.se/ca/cacert.pem -o build/public-certs.pem diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index dac1e6a..613cd97 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -1,3 +1,5 @@ +name: Release + on: push: branches: @@ -9,10 +11,16 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + + - name: Setup Bun + uses: oven-sh/setup-bun@v1 + + - name: Setup Node + uses: actions/setup-node@v4 with: - fetch-depth: 0 + node-version: latest - name: Create Release - run: npx semantic-release@v19.0.5 --debug --no-ci + run: bunx semantic-release env: GITHUB_TOKEN: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }} diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index e2f3639..046b7a8 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -12,22 +12,23 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version-file: .nvmrc + - name: Setup Bun + uses: oven-sh/setup-bun@v1 - name: Install - run: npm ci + run: bun i - name: Format - run: npm run format-check + run: bun run format-check - - name: Test - run: npm run test + - name: Type Check + run: bun tsc - name: Build - run: npm run build + run: bun run build + + - name: Test + run: bun run test docs: runs-on: ubuntu-latest diff --git a/.npmrc b/.npmrc deleted file mode 100644 index 38f11c6..0000000 --- a/.npmrc +++ /dev/null @@ -1 +0,0 @@ -registry=https://registry.npmjs.org diff --git a/.nvmrc b/.nvmrc deleted file mode 100644 index 8783404..0000000 --- a/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -20.12.2 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bc686e3..83085d2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,12 +1,12 @@ repos: -- repo: https://github.com/antonbabenko/pre-commit-terraform - rev: v1.71.0 # Get the latest from: https://github.com/antonbabenko/pre-commit-terraform/releases - hooks: - - id: terraform_fmt - - id: terraform_docs - #- id: terraform_validate - - id: terraform_tflint - args: - - 'args=--deep' - - 'args=--enable-rule=terraform_documented_variables' - - id: terraform_tfsec + - repo: https://github.com/antonbabenko/pre-commit-terraform + rev: v1.71.0 # Get the latest from: https://github.com/antonbabenko/pre-commit-terraform/releases + hooks: + - id: terraform_fmt + - id: terraform_docs + #- id: terraform_validate + - id: terraform_tflint + args: + - "args=--deep" + - "args=--enable-rule=terraform_documented_variables" + - id: terraform_tfsec diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index 376d748..0000000 --- a/.prettierrc.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "printWidth": 120, - "useTabs": false, - "singleQuote": true, - "trailingComma": "none", - "bracketSpacing": true, - "arrowParens": "avoid" -} diff --git a/.releaserc.yaml b/.releaserc.yaml index 1929e9b..75c3f26 100644 --- a/.releaserc.yaml +++ b/.releaserc.yaml @@ -1,5 +1,5 @@ plugins: - - - '@semantic-release/commit-analyzer' + - - "@semantic-release/commit-analyzer" - preset: angular releaseRules: - breaking: true @@ -12,8 +12,8 @@ plugins: release: patch - scope: no-release release: false - - '@semantic-release/release-notes-generator' - - - '@semantic-release/github' + - "@semantic-release/release-notes-generator" + - - "@semantic-release/github" - assets: - proxy-lambda.zip branches: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 607bd23..72fc849 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -48,7 +48,7 @@ Push your changes to your branch and open a pull request against the parent repo Upon Pull Request submission, your code will be reviewed by the maintainers. They will confirm at least the following: -- Tests run successfully (unit, coverage, integration, style). -- Contribution policy has been followed. +- Tests run successfully (unit, coverage, integration, style). +- Contribution policy has been followed. One (human) reviewer will need to sign off on your Pull Request before it can be merged. diff --git a/README.md b/README.md index 04ea250..976c5fd 100644 --- a/README.md +++ b/README.md @@ -17,11 +17,13 @@ aws s3 cp "${file}" "${s3_destination}/${file}" ``` Optionally, you may create a Lambda layer which optionally contains the following files: -* `allowed-destination-hosts.json`: An array of destination hosts that the proxy can forward to. If omitted, all destinations will be allowed. Wildcard matching is supported via [micromatch](https://github.com/micromatch/micromatch) -* `ca.pem`: A root CA certificate for forwarding to internal destinations with self-signed certs -* `cert.pem`: A chain certificate for forwarding to internal destinations with self-signed certs + +- `allowed-destination-hosts.json`: An array of destination hosts that the proxy can forward to. If omitted, all destinations will be allowed. Wildcard matching is supported via [micromatch](https://github.com/micromatch/micromatch) +- `ca.pem`: A root CA certificate for forwarding to internal destinations with self-signed certs +- `cert.pem`: A chain certificate for forwarding to internal destinations with self-signed certs These files must be in a zipped `layer` directory, and this can be uploaded using the following script: + ```shell # Zip and Upload Lambda Layer to s3_destination file="proxy-lambda-layer.zip" @@ -32,6 +34,7 @@ aws s3 cp "${file}" "${s3_destination}/${file}" If the layer is used, its ARN must be passed to the `lambda_layer_arn` Terraform variable. ### Example Terraform Module Usage + ```hcl module "github-webhook-proxy" { source = "git::https://github.com/ExpediaGroup/github-webhook-proxy.git?ref=v2" @@ -69,15 +72,15 @@ locals { ### Adding a New Webhook 1. **Create the webhook proxy URL** - 1. Obtain your desired destination URL, i.e. the internal endpoint where you want to send webhooks. - 2. Encode your destination URL! An easy way to do this is to use `jq` in your terminal - (install it [here](https://stedolan.github.io/jq/download/) if you don't have it already): `jq -rn --arg x 'YOUR_DESTINATION_URL_HERE' '$x|@uri'` - 3. Paste the encoded URL at the end of the webhook proxy base URL (`https://YOUR_API_URL/webhook`). + 1. Obtain your desired destination URL, i.e. the internal endpoint where you want to send webhooks. + 2. Encode your destination URL! An easy way to do this is to use `jq` in your terminal + (install it [here](https://stedolan.github.io/jq/download/) if you don't have it already): `jq -rn --arg x 'YOUR_DESTINATION_URL_HERE' '$x|@uri'` + 3. Paste the encoded URL at the end of the webhook proxy base URL (`https://YOUR_API_URL/webhook`). 2. **Add the webhook to your repository** - 1. As an administrator, navigate to your repository settings -> Webhooks -> Add webhook - 2. Paste your webhook proxy URL in the "Payload URL" box. You do not need to worry about "Content type". - 3. By default, GitHub will only send requests on the "push" event, but you may configure it to send on other events as well. - 4. Click "Add webhook" + 1. As an administrator, navigate to your repository settings -> Webhooks -> Add webhook + 2. Paste your webhook proxy URL in the "Payload URL" box. You do not need to worry about "Content type". + 3. By default, GitHub will only send requests on the "push" event, but you may configure it to send on other events as well. + 4. Click "Add webhook" ### Example Webhook Proxy URL Creation @@ -116,13 +119,14 @@ the `endpointId` to make it a valid URL. The Lambda then performs the following validations: -* The request must have an enterprise slug which matches the `enterprise_slug` environment variable, OR the request must +- The request must have an enterprise slug which matches the `enterprise_slug` environment variable, OR the request must come from a personal repository where the username ends in the enterprise managed user suffix (if provided). The user suffix is passed via the `enterprise_managed_user_suffix` Terraform variable. -* The request host must have an approved destination URL host, which is the decoded `endpointId` specified in the request +- The request host must have an approved destination URL host, which is the decoded `endpointId` specified in the request URL. The list of allowed destination hosts is read from `allowed-destination-hosts.json` in the Lambda layer. ### TLS Support + If a root and chain certificate are not provided in the Lambda layer, the runtime environment will supply certificates for requests. If these certificates are provided, however, the proxy will forward each request with `ca.pem` and `cert.pem` as the root and chain, respectively, with the root certificate appended to the [Mozilla CA certificate store](https://curl.se/docs/caextract.html). @@ -136,14 +140,16 @@ receives from the destination. If an unexpected error occurs, the webhook proxy ## Repository Overview ### Terraform Module + This repository contains Terraform (`*.tf`) files which are intended to be consumed as a Terraform module. The files are generally organized by resource type. See the "Resources" section in [USAGE.md](https://github.com/ExpediaGroup/github-webhook-proxy/tree/main/USAGE.md) for more infrastructure details. ### Lambda Function + The Lambda function is a Node.js Lambda compiled from Typescript, and lives in the ["lambda" directory](https://github.com/ExpediaGroup/github-webhook-proxy/tree/main/lambda). ### GitHub IP Range Allowlist + This repo has a GitHub Actions [workflow](https://github.com/ExpediaGroup/github-webhook-proxy/tree/main/.github/workflows/github-ip-ranges.yml) which checks that the [GitHub Hooks IP Ranges file](https://github.com/ExpediaGroup/github-webhook-proxy/tree/main/github-hooks-ip-ranges.tf) is up to date. It runs a script once a day which calls https://api.github.com/meta and ensures the IP ranges in "hooks" match our current IP allowlist in the API Gateway. If the list is out of date, it will create a PR to update it. - diff --git a/USAGE.md b/USAGE.md index ab18c80..7e025a9 100644 --- a/USAGE.md +++ b/USAGE.md @@ -1,15 +1,16 @@ + ## Requirements -| Name | Version | -|------|---------| -| [terraform](#requirement\_terraform) | 1.8.1 | +| Name | Version | +| ------------------------------------------------------------------------ | ------- | +| [terraform](#requirement_terraform) | 1.8.1 | ## Providers -| Name | Version | -|------|---------| -| [aws](#provider\_aws) | n/a | +| Name | Version | +| ------------------------------------------------ | ------- | +| [aws](#provider_aws) | n/a | ## Modules @@ -17,63 +18,64 @@ No modules. ## Resources -| Name | Type | -|------|------| -| [aws_api_gateway_base_path_mapping.dns_mapping](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_base_path_mapping) | resource | -| [aws_api_gateway_deployment.ingress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_deployment) | resource | -| [aws_api_gateway_domain_name.proxy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_domain_name) | resource | -| [aws_api_gateway_integration.lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_integration) | resource | -| [aws_api_gateway_method.lambda_method](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_method) | resource | -| [aws_api_gateway_method_settings.log_settings](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_method_settings) | resource | -| [aws_api_gateway_resource.lambda_endpoint](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_resource) | resource | -| [aws_api_gateway_resource.webhook](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_resource) | resource | -| [aws_api_gateway_rest_api.ingress_api](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_rest_api) | resource | -| [aws_api_gateway_rest_api_policy.allow_list](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_rest_api_policy) | resource | -| [aws_api_gateway_stage.ingress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_stage) | resource | -| [aws_cloudwatch_dashboard.metrics](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_dashboard) | resource | -| [aws_cloudwatch_log_group.apigw](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | -| [aws_cloudwatch_log_group.lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | -| [aws_iam_role.proxy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role_policy.apigw_logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | -| [aws_iam_role_policy.extra_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | -| [aws_iam_role_policy.lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | -| [aws_iam_role_policy_attachment.basic_execution](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_iam_role_policy_attachment.vpc_execution](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | -| [aws_lambda_function.proxy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | -| [aws_lambda_permission.apigw_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | -| [aws_route53_record.proxy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource | -| [aws_security_group.lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | -| [aws_iam_policy_document.allow_list](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.apigw_logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.lambda_logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_iam_policy_document.proxy_service](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | -| [aws_s3_object.proxy_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/s3_object) | data source | +| Name | Type | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | +| [aws_api_gateway_base_path_mapping.dns_mapping](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_base_path_mapping) | resource | +| [aws_api_gateway_deployment.ingress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_deployment) | resource | +| [aws_api_gateway_domain_name.proxy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_domain_name) | resource | +| [aws_api_gateway_integration.lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_integration) | resource | +| [aws_api_gateway_method.lambda_method](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_method) | resource | +| [aws_api_gateway_method_settings.log_settings](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_method_settings) | resource | +| [aws_api_gateway_resource.lambda_endpoint](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_resource) | resource | +| [aws_api_gateway_resource.webhook](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_resource) | resource | +| [aws_api_gateway_rest_api.ingress_api](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_rest_api) | resource | +| [aws_api_gateway_rest_api_policy.allow_list](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_rest_api_policy) | resource | +| [aws_api_gateway_stage.ingress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/api_gateway_stage) | resource | +| [aws_cloudwatch_dashboard.metrics](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_dashboard) | resource | +| [aws_cloudwatch_log_group.apigw](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_cloudwatch_log_group.lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | +| [aws_iam_role.proxy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy.apigw_logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.extra_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy_attachment.basic_execution](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_iam_role_policy_attachment.vpc_execution](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_lambda_function.proxy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | +| [aws_lambda_permission.apigw_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | +| [aws_route53_record.proxy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_record) | resource | +| [aws_security_group.lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | +| [aws_iam_policy_document.allow_list](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.apigw_logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.lambda_logging](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.proxy_service](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_s3_object.proxy_lambda](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/s3_object) | data source | ## Inputs -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| [api\_gateway\_domain\_name](#input\_api\_gateway\_domain\_name) | Domain name for API gateway domain mapping | `string` | `null` | no | -| [aws\_region](#input\_aws\_region) | The AWS region to deploy to (e.g. us-east-1) | `string` | n/a | yes | -| [certificate\_arn](#input\_certificate\_arn) | Certificate ARN for API gateway domain name | `string` | `null` | no | -| [custom\_tags](#input\_custom\_tags) | Additional tags to be applied to all resources applied by this module. | `map(string)` | `{}` | no | -| [enterprise\_managed\_user\_suffix](#input\_enterprise\_managed\_user\_suffix) | Managed user suffix used for central identity management on GHEC | `string` | `""` | no | -| [enterprise\_slug](#input\_enterprise\_slug) | The name (slug) of the enterprise on GHEC | `string` | n/a | yes | -| [extra\_role\_policy](#input\_extra\_role\_policy) | jsonencoded string policy to include in the proxy lambda role | `string` | `null` | no | -| [lambda\_bucket\_name](#input\_lambda\_bucket\_name) | S3 bucket with lambda and layer archives | `string` | n/a | yes | -| [lambda\_layer\_arn](#input\_lambda\_layer\_arn) | Lambda layer ARN for data store | `string` | n/a | yes | -| [lambda\_timeout\_seconds](#input\_lambda\_timeout\_seconds) | Number of seconds until lambda times out | `number` | `10` | no | -| [log\_retention\_days](#input\_log\_retention\_days) | Number of days CloudWatch will retain logs | `number` | `7` | no | -| [resource\_prefix](#input\_resource\_prefix) | Prefix of webhook proxy resources | `string` | `"gwp"` | no | -| [route\_53\_record\_name](#input\_route\_53\_record\_name) | Record name for Route 53 record creation | `string` | `null` | no | -| [subnet\_ids](#input\_subnet\_ids) | subnet\_ids for Lambda VPC config | `list(string)` | n/a | yes | -| [vpc\_id](#input\_vpc\_id) | VPC id for Lambda VPC config | `string` | n/a | yes | -| [zone\_id](#input\_zone\_id) | Zone id for Route53 record | `string` | `null` | no | +| Name | Description | Type | Default | Required | +| --------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | -------------- | ------- | :------: | +| [api_gateway_domain_name](#input_api_gateway_domain_name) | Domain name for API gateway domain mapping | `string` | `null` | no | +| [aws_region](#input_aws_region) | The AWS region to deploy to (e.g. us-east-1) | `string` | n/a | yes | +| [certificate_arn](#input_certificate_arn) | Certificate ARN for API gateway domain name | `string` | `null` | no | +| [custom_tags](#input_custom_tags) | Additional tags to be applied to all resources applied by this module. | `map(string)` | `{}` | no | +| [enterprise_managed_user_suffix](#input_enterprise_managed_user_suffix) | Managed user suffix used for central identity management on GHEC | `string` | `""` | no | +| [enterprise_slug](#input_enterprise_slug) | The name (slug) of the enterprise on GHEC | `string` | n/a | yes | +| [extra_role_policy](#input_extra_role_policy) | jsonencoded string policy to include in the proxy lambda role | `string` | `null` | no | +| [lambda_bucket_name](#input_lambda_bucket_name) | S3 bucket with lambda and layer archives | `string` | n/a | yes | +| [lambda_layer_arn](#input_lambda_layer_arn) | Lambda layer ARN for data store | `string` | n/a | yes | +| [lambda_timeout_seconds](#input_lambda_timeout_seconds) | Number of seconds until lambda times out | `number` | `10` | no | +| [log_retention_days](#input_log_retention_days) | Number of days CloudWatch will retain logs | `number` | `7` | no | +| [resource_prefix](#input_resource_prefix) | Prefix of webhook proxy resources | `string` | `"gwp"` | no | +| [route_53_record_name](#input_route_53_record_name) | Record name for Route 53 record creation | `string` | `null` | no | +| [subnet_ids](#input_subnet_ids) | subnet_ids for Lambda VPC config | `list(string)` | n/a | yes | +| [vpc_id](#input_vpc_id) | VPC id for Lambda VPC config | `string` | n/a | yes | +| [zone_id](#input_zone_id) | Zone id for Route53 record | `string` | `null` | no | ## Outputs -| Name | Description | -|------|-------------| -| [apigateway\_ingress\_id](#output\_apigateway\_ingress\_id) | n/a | -| [apigateway\_invoke\_url](#output\_apigateway\_invoke\_url) | n/a | - \ No newline at end of file +| Name | Description | +| -------------------------------------------------------------------------------------------------- | ----------- | +| [apigateway_ingress_id](#output_apigateway_ingress_id) | n/a | +| [apigateway_invoke_url](#output_apigateway_invoke_url) | n/a | + + diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000..aa954e9 Binary files /dev/null and b/bun.lockb differ diff --git a/dashboard.json b/dashboard.json index c4e82dc..b6256c7 100644 --- a/dashboard.json +++ b/dashboard.json @@ -36,11 +36,70 @@ "type": "metric", "properties": { "metrics": [ - [ "AWS/ApiGateway", "Latency", "ApiName", "gwp-default-ingress", "Resource", "/webhook/{endpointId}", "Stage", "v1", "Method", "POST" ], - [ ".", "Count", ".", ".", ".", ".", ".", ".", ".", ".", { "visible": false } ], - [ ".", "IntegrationLatency", ".", ".", ".", ".", ".", ".", ".", ".", { "visible": false } ], - [ ".", "4XXError", ".", ".", ".", ".", ".", ".", ".", ".", { "visible": false } ], - [ ".", "5XXError", ".", ".", ".", ".", ".", ".", ".", ".", { "visible": false } ] + [ + "AWS/ApiGateway", + "Latency", + "ApiName", + "gwp-default-ingress", + "Resource", + "/webhook/{endpointId}", + "Stage", + "v1", + "Method", + "POST" + ], + [ + ".", + "Count", + ".", + ".", + ".", + ".", + ".", + ".", + ".", + ".", + { "visible": false } + ], + [ + ".", + "IntegrationLatency", + ".", + ".", + ".", + ".", + ".", + ".", + ".", + ".", + { "visible": false } + ], + [ + ".", + "4XXError", + ".", + ".", + ".", + ".", + ".", + ".", + ".", + ".", + { "visible": false } + ], + [ + ".", + "5XXError", + ".", + ".", + ".", + ".", + ".", + ".", + ".", + ".", + { "visible": false } + ] ], "view": "timeSeries", "region": "us-west-2", @@ -58,7 +117,18 @@ "type": "metric", "properties": { "metrics": [ - [ "AWS/ApiGateway", "Count", "ApiName", "gwp-default-ingress", "Resource", "/webhook/{endpointId}", "Stage", "v1", "Method", "POST" ] + [ + "AWS/ApiGateway", + "Count", + "ApiName", + "gwp-default-ingress", + "Resource", + "/webhook/{endpointId}", + "Stage", + "v1", + "Method", + "POST" + ] ], "view": "timeSeries", "region": "us-west-2", diff --git a/fixtures/valid-ping-payload.ts b/fixtures/valid-ping-payload.ts index 04c88d6..94e5e28 100644 --- a/fixtures/valid-ping-payload.ts +++ b/fixtures/valid-ping-payload.ts @@ -1,104 +1,141 @@ -import { PingEvent } from '../lambda/types'; +import { PingEvent } from "../lambda/types"; export const VALID_PING_EVENT: PingEvent = { - zen: 'Design for failure.', + zen: "Design for failure.", hook_id: 391282347, hook: { - type: 'Repository', + type: "Repository", id: 391282347, - name: 'web', + name: "web", active: true, - events: ['push'], + events: ["push"], config: { - content_type: 'json', - url: 'https://approved.host/github-webhook/', - insecure_ssl: '0' + content_type: "json", + url: "https://approved.host/github-webhook/", + insecure_ssl: "0", }, - updated_at: '2022-12-05T20:28:34Z', - created_at: '2022-12-05T20:28:34Z', - url: 'https://api.github.com/repos/github-org/github-repo/hooks/391282347', - test_url: 'https://api.github.com/repos/github-org/github-repo/hooks/391282347/test', - ping_url: 'https://api.github.com/repos/github-org/github-repo/hooks/391282347/pings', - deliveries_url: 'https://api.github.com/repos/github-org/github-repo/hooks/391282347/deliveries', + updated_at: "2022-12-05T20:28:34Z", + created_at: "2022-12-05T20:28:34Z", + url: "https://api.github.com/repos/github-org/github-repo/hooks/391282347", + test_url: + "https://api.github.com/repos/github-org/github-repo/hooks/391282347/test", + ping_url: + "https://api.github.com/repos/github-org/github-repo/hooks/391282347/pings", + deliveries_url: + "https://api.github.com/repos/github-org/github-repo/hooks/391282347/deliveries", last_response: { code: null, - status: 'unused', - message: null - } + status: "unused", + message: null, + }, }, repository: { id: 567006112, - node_id: 'R_kgDOIcvToA', - name: 'github-repo', - full_name: 'github-org/github-repo', + node_id: "R_kgDOIcvToA", + name: "github-repo", + full_name: "github-org/github-repo", private: true, owner: { - login: 'github-org', + login: "github-org", id: 107203838, - node_id: 'O_kgDOBmPM_g', - avatar_url: 'https://avatars.githubusercontent.com/u/107203838?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/github-org', - html_url: 'https://github.com/github-org', - followers_url: 'https://api.github.com/users/github-org/followers', - following_url: 'https://api.github.com/users/github-org/following{/other_user}', - gists_url: 'https://api.github.com/users/github-org/gists{/gist_id}', - starred_url: 'https://api.github.com/users/github-org/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/github-org/subscriptions', - organizations_url: 'https://api.github.com/users/github-org/orgs', - repos_url: 'https://api.github.com/users/github-org/repos', - events_url: 'https://api.github.com/users/github-org/events{/privacy}', - received_events_url: 'https://api.github.com/users/github-org/received_events', - type: 'Organization', - site_admin: false + node_id: "O_kgDOBmPM_g", + avatar_url: "https://avatars.githubusercontent.com/u/107203838?v=4", + gravatar_id: "", + url: "https://api.github.com/users/github-org", + html_url: "https://github.com/github-org", + followers_url: "https://api.github.com/users/github-org/followers", + following_url: + "https://api.github.com/users/github-org/following{/other_user}", + gists_url: "https://api.github.com/users/github-org/gists{/gist_id}", + starred_url: + "https://api.github.com/users/github-org/starred{/owner}{/repo}", + subscriptions_url: + "https://api.github.com/users/github-org/subscriptions", + organizations_url: "https://api.github.com/users/github-org/orgs", + repos_url: "https://api.github.com/users/github-org/repos", + events_url: "https://api.github.com/users/github-org/events{/privacy}", + received_events_url: + "https://api.github.com/users/github-org/received_events", + type: "Organization", + site_admin: false, }, - html_url: 'https://github.com/github-org/github-repo', + html_url: "https://github.com/github-org/github-repo", description: null, fork: false, - url: 'https://api.github.com/repos/github-org/github-repo', - forks_url: 'https://api.github.com/repos/github-org/github-repo/forks', - keys_url: 'https://api.github.com/repos/github-org/github-repo/keys{/key_id}', - collaborators_url: 'https://api.github.com/repos/github-org/github-repo/collaborators{/collaborator}', - teams_url: 'https://api.github.com/repos/github-org/github-repo/teams', - hooks_url: 'https://api.github.com/repos/github-org/github-repo/hooks', - issue_events_url: 'https://api.github.com/repos/github-org/github-repo/issues/events{/number}', - events_url: 'https://api.github.com/repos/github-org/github-repo/events', - assignees_url: 'https://api.github.com/repos/github-org/github-repo/assignees{/user}', - branches_url: 'https://api.github.com/repos/github-org/github-repo/branches{/branch}', - tags_url: 'https://api.github.com/repos/github-org/github-repo/tags', - blobs_url: 'https://api.github.com/repos/github-org/github-repo/git/blobs{/sha}', - git_tags_url: 'https://api.github.com/repos/github-org/github-repo/git/tags{/sha}', - git_refs_url: 'https://api.github.com/repos/github-org/github-repo/git/refs{/sha}', - trees_url: 'https://api.github.com/repos/github-org/github-repo/git/trees{/sha}', - statuses_url: 'https://api.github.com/repos/github-org/github-repo/statuses/{sha}', - languages_url: 'https://api.github.com/repos/github-org/github-repo/languages', - stargazers_url: 'https://api.github.com/repos/github-org/github-repo/stargazers', - contributors_url: 'https://api.github.com/repos/github-org/github-repo/contributors', - subscribers_url: 'https://api.github.com/repos/github-org/github-repo/subscribers', - subscription_url: 'https://api.github.com/repos/github-org/github-repo/subscription', - commits_url: 'https://api.github.com/repos/github-org/github-repo/commits{/sha}', - git_commits_url: 'https://api.github.com/repos/github-org/github-repo/git/commits{/sha}', - comments_url: 'https://api.github.com/repos/github-org/github-repo/comments{/number}', - issue_comment_url: 'https://api.github.com/repos/github-org/github-repo/issues/comments{/number}', - contents_url: 'https://api.github.com/repos/github-org/github-repo/contents/{+path}', - compare_url: 'https://api.github.com/repos/github-org/github-repo/compare/{base}...{head}', - merges_url: 'https://api.github.com/repos/github-org/github-repo/merges', - archive_url: 'https://api.github.com/repos/github-org/github-repo/{archive_format}{/ref}', - downloads_url: 'https://api.github.com/repos/github-org/github-repo/downloads', - issues_url: 'https://api.github.com/repos/github-org/github-repo/issues{/number}', - pulls_url: 'https://api.github.com/repos/github-org/github-repo/pulls{/number}', - milestones_url: 'https://api.github.com/repos/github-org/github-repo/milestones{/number}', - notifications_url: 'https://api.github.com/repos/github-org/github-repo/notifications{?since,all,participating}', - labels_url: 'https://api.github.com/repos/github-org/github-repo/labels{/name}', - releases_url: 'https://api.github.com/repos/github-org/github-repo/releases{/id}', - deployments_url: 'https://api.github.com/repos/github-org/github-repo/deployments', - created_at: '2022-11-16T21:46:21Z', - updated_at: '2022-11-16T21:46:21Z', - pushed_at: '2022-12-05T19:36:08Z', - git_url: 'git://github.com/github-org/github-repo.git', - ssh_url: 'git@github.com:github-org/github-repo.git', - clone_url: 'https://github.com/github-org/github-repo.git', - svn_url: 'https://github.com/github-org/github-repo', + url: "https://api.github.com/repos/github-org/github-repo", + forks_url: "https://api.github.com/repos/github-org/github-repo/forks", + keys_url: + "https://api.github.com/repos/github-org/github-repo/keys{/key_id}", + collaborators_url: + "https://api.github.com/repos/github-org/github-repo/collaborators{/collaborator}", + teams_url: "https://api.github.com/repos/github-org/github-repo/teams", + hooks_url: "https://api.github.com/repos/github-org/github-repo/hooks", + issue_events_url: + "https://api.github.com/repos/github-org/github-repo/issues/events{/number}", + events_url: "https://api.github.com/repos/github-org/github-repo/events", + assignees_url: + "https://api.github.com/repos/github-org/github-repo/assignees{/user}", + branches_url: + "https://api.github.com/repos/github-org/github-repo/branches{/branch}", + tags_url: "https://api.github.com/repos/github-org/github-repo/tags", + blobs_url: + "https://api.github.com/repos/github-org/github-repo/git/blobs{/sha}", + git_tags_url: + "https://api.github.com/repos/github-org/github-repo/git/tags{/sha}", + git_refs_url: + "https://api.github.com/repos/github-org/github-repo/git/refs{/sha}", + trees_url: + "https://api.github.com/repos/github-org/github-repo/git/trees{/sha}", + statuses_url: + "https://api.github.com/repos/github-org/github-repo/statuses/{sha}", + languages_url: + "https://api.github.com/repos/github-org/github-repo/languages", + stargazers_url: + "https://api.github.com/repos/github-org/github-repo/stargazers", + contributors_url: + "https://api.github.com/repos/github-org/github-repo/contributors", + subscribers_url: + "https://api.github.com/repos/github-org/github-repo/subscribers", + subscription_url: + "https://api.github.com/repos/github-org/github-repo/subscription", + commits_url: + "https://api.github.com/repos/github-org/github-repo/commits{/sha}", + git_commits_url: + "https://api.github.com/repos/github-org/github-repo/git/commits{/sha}", + comments_url: + "https://api.github.com/repos/github-org/github-repo/comments{/number}", + issue_comment_url: + "https://api.github.com/repos/github-org/github-repo/issues/comments{/number}", + contents_url: + "https://api.github.com/repos/github-org/github-repo/contents/{+path}", + compare_url: + "https://api.github.com/repos/github-org/github-repo/compare/{base}...{head}", + merges_url: "https://api.github.com/repos/github-org/github-repo/merges", + archive_url: + "https://api.github.com/repos/github-org/github-repo/{archive_format}{/ref}", + downloads_url: + "https://api.github.com/repos/github-org/github-repo/downloads", + issues_url: + "https://api.github.com/repos/github-org/github-repo/issues{/number}", + pulls_url: + "https://api.github.com/repos/github-org/github-repo/pulls{/number}", + milestones_url: + "https://api.github.com/repos/github-org/github-repo/milestones{/number}", + notifications_url: + "https://api.github.com/repos/github-org/github-repo/notifications{?since,all,participating}", + labels_url: + "https://api.github.com/repos/github-org/github-repo/labels{/name}", + releases_url: + "https://api.github.com/repos/github-org/github-repo/releases{/id}", + deployments_url: + "https://api.github.com/repos/github-org/github-repo/deployments", + created_at: "2022-11-16T21:46:21Z", + updated_at: "2022-11-16T21:46:21Z", + pushed_at: "2022-12-05T19:36:08Z", + git_url: "git://github.com/github-org/github-repo.git", + ssh_url: "git@github.com:github-org/github-repo.git", + clone_url: "https://github.com/github-org/github-repo.git", + svn_url: "https://github.com/github-org/github-repo", homepage: null, size: 25, stargazers_count: 0, @@ -119,30 +156,34 @@ export const VALID_PING_EVENT: PingEvent = { is_template: false, web_commit_signoff_required: false, topics: [], - visibility: 'internal', + visibility: "internal", forks: 0, open_issues: 0, watchers: 0, - default_branch: 'main' + default_branch: "main", }, sender: { - login: 'username_suffix', + login: "username_suffix", id: 118491937, - node_id: 'U_kgDOBxALIQ', - avatar_url: 'https://avatars.githubusercontent.com/u/118491937?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/username_suffix', - html_url: 'https://github.com/username_suffix', - followers_url: 'https://api.github.com/users/username_suffix/followers', - following_url: 'https://api.github.com/users/username_suffix/following{/other_user}', - gists_url: 'https://api.github.com/users/username_suffix/gists{/gist_id}', - starred_url: 'https://api.github.com/users/username_suffix/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/username_suffix/subscriptions', - organizations_url: 'https://api.github.com/users/username_suffix/orgs', - repos_url: 'https://api.github.com/users/username_suffix/repos', - events_url: 'https://api.github.com/users/username_suffix/events{/privacy}', - received_events_url: 'https://api.github.com/users/username_suffix/received_events', - type: 'User', - site_admin: false - } + node_id: "U_kgDOBxALIQ", + avatar_url: "https://avatars.githubusercontent.com/u/118491937?v=4", + gravatar_id: "", + url: "https://api.github.com/users/username_suffix", + html_url: "https://github.com/username_suffix", + followers_url: "https://api.github.com/users/username_suffix/followers", + following_url: + "https://api.github.com/users/username_suffix/following{/other_user}", + gists_url: "https://api.github.com/users/username_suffix/gists{/gist_id}", + starred_url: + "https://api.github.com/users/username_suffix/starred{/owner}{/repo}", + subscriptions_url: + "https://api.github.com/users/username_suffix/subscriptions", + organizations_url: "https://api.github.com/users/username_suffix/orgs", + repos_url: "https://api.github.com/users/username_suffix/repos", + events_url: "https://api.github.com/users/username_suffix/events{/privacy}", + received_events_url: + "https://api.github.com/users/username_suffix/received_events", + type: "User", + site_admin: false, + }, }; diff --git a/fixtures/valid-push-payload-user-repo.ts b/fixtures/valid-push-payload-user-repo.ts index e1b1444..aed2e0e 100644 --- a/fixtures/valid-push-payload-user-repo.ts +++ b/fixtures/valid-push-payload-user-repo.ts @@ -1,85 +1,125 @@ -import { PushEvent } from '../lambda/types'; +import { PushEvent } from "../lambda/types"; export const VALID_PUSH_PAYLOAD_USER_REPO: PushEvent = { - ref: 'refs/heads/main', - before: '448223ee31c525296e09832c0da95559015f500c', - after: '7119b388e221a96ced5e1dfa0528d51847828308', + ref: "refs/heads/main", + before: "448223ee31c525296e09832c0da95559015f500c", + after: "7119b388e221a96ced5e1dfa0528d51847828308", repository: { id: 482984142, - node_id: 'R_kgDOHMnAzg', - name: 'github-webhook-proxy', - full_name: 'username_suffix/github-webhook-proxy', + node_id: "R_kgDOHMnAzg", + name: "github-webhook-proxy", + full_name: "username_suffix/github-webhook-proxy", private: true, owner: { - name: 'username_suffix', - email: 'user@ExampleOrg.com', - login: 'username_suffix', + name: "username_suffix", + email: "user@ExampleOrg.com", + login: "username_suffix", id: 103291641, - node_id: 'U_kgDOBiga-Q', - avatar_url: 'https://avatars.githubusercontent.com/u/103291641?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/username_suffix', - html_url: 'https://github.com/username_suffix', - followers_url: 'https://api.github.com/users/username_suffix/followers', - following_url: 'https://api.github.com/users/username_suffix/following{/other_user}', - gists_url: 'https://api.github.com/users/username_suffix/gists{/gist_id}', - starred_url: 'https://api.github.com/users/username_suffix/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/username_suffix/subscriptions', - organizations_url: 'https://api.github.com/users/username_suffix/orgs', - repos_url: 'https://api.github.com/users/username_suffix/repos', - events_url: 'https://api.github.com/users/username_suffix/events{/privacy}', - received_events_url: 'https://api.github.com/users/username_suffix/received_events', - type: 'User', - site_admin: false + node_id: "U_kgDOBiga-Q", + avatar_url: "https://avatars.githubusercontent.com/u/103291641?v=4", + gravatar_id: "", + url: "https://api.github.com/users/username_suffix", + html_url: "https://github.com/username_suffix", + followers_url: "https://api.github.com/users/username_suffix/followers", + following_url: + "https://api.github.com/users/username_suffix/following{/other_user}", + gists_url: "https://api.github.com/users/username_suffix/gists{/gist_id}", + starred_url: + "https://api.github.com/users/username_suffix/starred{/owner}{/repo}", + subscriptions_url: + "https://api.github.com/users/username_suffix/subscriptions", + organizations_url: "https://api.github.com/users/username_suffix/orgs", + repos_url: "https://api.github.com/users/username_suffix/repos", + events_url: + "https://api.github.com/users/username_suffix/events{/privacy}", + received_events_url: + "https://api.github.com/users/username_suffix/received_events", + type: "User", + site_admin: false, }, - html_url: 'https://github.com/username_suffix/github-webhook-proxy', + html_url: "https://github.com/username_suffix/github-webhook-proxy", description: null, fork: false, - url: 'https://github.com/username_suffix/github-webhook-proxy', - forks_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/forks', - keys_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/keys{/key_id}', - collaborators_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/collaborators{/collaborator}', - teams_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/teams', - hooks_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/hooks', - issue_events_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/issues/events{/number}', - events_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/events', - assignees_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/assignees{/user}', - branches_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/branches{/branch}', - tags_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/tags', - blobs_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/git/blobs{/sha}', - git_tags_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/git/tags{/sha}', - git_refs_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/git/refs{/sha}', - trees_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/git/trees{/sha}', - statuses_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/statuses/{sha}', - languages_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/languages', - stargazers_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/stargazers', - contributors_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/contributors', - subscribers_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/subscribers', - subscription_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/subscription', - commits_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/commits{/sha}', - git_commits_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/git/commits{/sha}', - comments_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/comments{/number}', - issue_comment_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/issues/comments{/number}', - contents_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/contents/{+path}', - compare_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/compare/{base}...{head}', - merges_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/merges', - archive_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/{archive_format}{/ref}', - downloads_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/downloads', - issues_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/issues{/number}', - pulls_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/pulls{/number}', - milestones_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/milestones{/number}', + url: "https://github.com/username_suffix/github-webhook-proxy", + forks_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/forks", + keys_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/keys{/key_id}", + collaborators_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/collaborators{/collaborator}", + teams_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/teams", + hooks_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/hooks", + issue_events_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/issues/events{/number}", + events_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/events", + assignees_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/assignees{/user}", + branches_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/branches{/branch}", + tags_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/tags", + blobs_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/git/blobs{/sha}", + git_tags_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/git/tags{/sha}", + git_refs_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/git/refs{/sha}", + trees_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/git/trees{/sha}", + statuses_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/statuses/{sha}", + languages_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/languages", + stargazers_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/stargazers", + contributors_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/contributors", + subscribers_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/subscribers", + subscription_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/subscription", + commits_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/commits{/sha}", + git_commits_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/git/commits{/sha}", + comments_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/comments{/number}", + issue_comment_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/issues/comments{/number}", + contents_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/contents/{+path}", + compare_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/compare/{base}...{head}", + merges_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/merges", + archive_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/{archive_format}{/ref}", + downloads_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/downloads", + issues_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/issues{/number}", + pulls_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/pulls{/number}", + milestones_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/milestones{/number}", notifications_url: - 'https://api.github.com/repos/username_suffix/github-webhook-proxy/notifications{?since,all,participating}', - labels_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/labels{/name}', - releases_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/releases{/id}', - deployments_url: 'https://api.github.com/repos/username_suffix/github-webhook-proxy/deployments', + "https://api.github.com/repos/username_suffix/github-webhook-proxy/notifications{?since,all,participating}", + labels_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/labels{/name}", + releases_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/releases{/id}", + deployments_url: + "https://api.github.com/repos/username_suffix/github-webhook-proxy/deployments", created_at: 1650312935, - updated_at: '2022-04-19T12:27:56Z', + updated_at: "2022-04-19T12:27:56Z", pushed_at: 1650489516, - git_url: 'git://github.com/username_suffix/github-webhook-proxy.git', - ssh_url: 'git@github.com:username_suffix/github-webhook-proxy.git', - clone_url: 'https://github.com/username_suffix/github-webhook-proxy.git', - svn_url: 'https://github.com/username_suffix/github-webhook-proxy', + git_url: "git://github.com/username_suffix/github-webhook-proxy.git", + ssh_url: "git@github.com:username_suffix/github-webhook-proxy.git", + clone_url: "https://github.com/username_suffix/github-webhook-proxy.git", + svn_url: "https://github.com/username_suffix/github-webhook-proxy", homepage: null, size: 3, stargazers_count: 0, @@ -100,82 +140,87 @@ export const VALID_PUSH_PAYLOAD_USER_REPO: PushEvent = { is_template: false, web_commit_signoff_required: false, topics: [], - visibility: 'private', + visibility: "private", forks: 0, open_issues: 0, watchers: 0, - default_branch: 'main', + default_branch: "main", stargazers: 0, - master_branch: 'main', - has_discussions: false + master_branch: "main", + has_discussions: false, }, pusher: { - name: 'username_suffix', - email: 'user@ExampleOrg.com' + name: "username_suffix", + email: "user@ExampleOrg.com", }, sender: { - login: 'username_suffix', + login: "username_suffix", id: 103291641, - node_id: 'U_kgDOBiga-Q', - avatar_url: 'https://avatars.githubusercontent.com/u/103291641?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/username_suffix', - html_url: 'https://github.com/username_suffix', - followers_url: 'https://api.github.com/users/username_suffix/followers', - following_url: 'https://api.github.com/users/username_suffix/following{/other_user}', - gists_url: 'https://api.github.com/users/username_suffix/gists{/gist_id}', - starred_url: 'https://api.github.com/users/username_suffix/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/username_suffix/subscriptions', - organizations_url: 'https://api.github.com/users/username_suffix/orgs', - repos_url: 'https://api.github.com/users/username_suffix/repos', - events_url: 'https://api.github.com/users/username_suffix/events{/privacy}', - received_events_url: 'https://api.github.com/users/username_suffix/received_events', - type: 'User', - site_admin: false + node_id: "U_kgDOBiga-Q", + avatar_url: "https://avatars.githubusercontent.com/u/103291641?v=4", + gravatar_id: "", + url: "https://api.github.com/users/username_suffix", + html_url: "https://github.com/username_suffix", + followers_url: "https://api.github.com/users/username_suffix/followers", + following_url: + "https://api.github.com/users/username_suffix/following{/other_user}", + gists_url: "https://api.github.com/users/username_suffix/gists{/gist_id}", + starred_url: + "https://api.github.com/users/username_suffix/starred{/owner}{/repo}", + subscriptions_url: + "https://api.github.com/users/username_suffix/subscriptions", + organizations_url: "https://api.github.com/users/username_suffix/orgs", + repos_url: "https://api.github.com/users/username_suffix/repos", + events_url: "https://api.github.com/users/username_suffix/events{/privacy}", + received_events_url: + "https://api.github.com/users/username_suffix/received_events", + type: "User", + site_admin: false, }, created: false, deleted: false, forced: false, base_ref: null, - compare: 'https://github.com/username_suffix/github-webhook-proxy/compare/448223ee31c5...7119b388e221', + compare: + "https://github.com/username_suffix/github-webhook-proxy/compare/448223ee31c5...7119b388e221", commits: [ { - id: '7119b388e221a96ced5e1dfa0528d51847828308', - tree_id: 'e5d86be93b96d8389e85e1e34560e936786e6ec2', + id: "7119b388e221a96ced5e1dfa0528d51847828308", + tree_id: "e5d86be93b96d8389e85e1e34560e936786e6ec2", distinct: true, - message: 'dummy commit', - timestamp: '2022-04-20T17:18:32-04:00', - url: 'https://github.com/username_suffix/github-webhook-proxy/commit/7119b388e221a96ced5e1dfa0528d51847828308', + message: "dummy commit", + timestamp: "2022-04-20T17:18:32-04:00", + url: "https://github.com/username_suffix/github-webhook-proxy/commit/7119b388e221a96ced5e1dfa0528d51847828308", author: { - name: 'user', - email: 'user@ExampleOrg.com' + name: "user", + email: "user@ExampleOrg.com", }, committer: { - name: 'user', - email: 'user@ExampleOrg.com' + name: "user", + email: "user@ExampleOrg.com", }, added: [], removed: [], - modified: [] - } + modified: [], + }, ], head_commit: { - id: '7119b388e221a96ced5e1dfa0528d51847828308', - tree_id: 'e5d86be93b96d8389e85e1e34560e936786e6ec2', + id: "7119b388e221a96ced5e1dfa0528d51847828308", + tree_id: "e5d86be93b96d8389e85e1e34560e936786e6ec2", distinct: true, - message: 'dummy commit', - timestamp: '2022-04-20T17:18:32-04:00', - url: 'https://github.com/username_suffix/github-webhook-proxy/commit/7119b388e221a96ced5e1dfa0528d51847828308', + message: "dummy commit", + timestamp: "2022-04-20T17:18:32-04:00", + url: "https://github.com/username_suffix/github-webhook-proxy/commit/7119b388e221a96ced5e1dfa0528d51847828308", author: { - name: 'user', - email: 'user@ExampleOrg.com' + name: "user", + email: "user@ExampleOrg.com", }, committer: { - name: 'user', - email: 'user@ExampleOrg.com' + name: "user", + email: "user@ExampleOrg.com", }, added: [], removed: [], - modified: [] - } + modified: [], + }, }; diff --git a/fixtures/valid-push-payload.ts b/fixtures/valid-push-payload.ts index df32c6d..e1b4280 100644 --- a/fixtures/valid-push-payload.ts +++ b/fixtures/valid-push-payload.ts @@ -1,85 +1,124 @@ -import { PushEvent } from '../lambda/types'; +import { PushEvent } from "../lambda/types"; export const VALID_PUSH_PAYLOAD: PushEvent = { - ref: 'refs/heads/main', - before: '448223ee31c525296e09832c0da95559015f500c', - after: '7119b388e221a96ced5e1dfa0528d51847828308', + ref: "refs/heads/main", + before: "448223ee31c525296e09832c0da95559015f500c", + after: "7119b388e221a96ced5e1dfa0528d51847828308", repository: { id: 482984142, - node_id: 'R_kgDOHMnAzg', - name: 'github-webhook-proxy', - full_name: 'ExampleOrg/github-webhook-proxy', + node_id: "R_kgDOHMnAzg", + name: "github-webhook-proxy", + full_name: "ExampleOrg/github-webhook-proxy", private: true, owner: { - name: 'ExampleOrg', - email: 'user@ExampleOrg.com', - login: 'ExampleOrg', + name: "ExampleOrg", + email: "user@ExampleOrg.com", + login: "ExampleOrg", id: 103291641, - node_id: 'U_kgDOBiga-Q', - avatar_url: 'https://avatars.githubusercontent.com/u/103291641?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/ExampleOrg', - html_url: 'https://github.com/ExampleOrg', - followers_url: 'https://api.github.com/users/ExampleOrg/followers', - following_url: 'https://api.github.com/users/ExampleOrg/following{/other_user}', - gists_url: 'https://api.github.com/users/ExampleOrg/gists{/gist_id}', - starred_url: 'https://api.github.com/users/ExampleOrg/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/ExampleOrg/subscriptions', - organizations_url: 'https://api.github.com/users/ExampleOrg/orgs', - repos_url: 'https://api.github.com/users/ExampleOrg/repos', - events_url: 'https://api.github.com/users/ExampleOrg/events{/privacy}', - received_events_url: 'https://api.github.com/users/ExampleOrg/received_events', - type: 'User', - site_admin: false + node_id: "U_kgDOBiga-Q", + avatar_url: "https://avatars.githubusercontent.com/u/103291641?v=4", + gravatar_id: "", + url: "https://api.github.com/users/ExampleOrg", + html_url: "https://github.com/ExampleOrg", + followers_url: "https://api.github.com/users/ExampleOrg/followers", + following_url: + "https://api.github.com/users/ExampleOrg/following{/other_user}", + gists_url: "https://api.github.com/users/ExampleOrg/gists{/gist_id}", + starred_url: + "https://api.github.com/users/ExampleOrg/starred{/owner}{/repo}", + subscriptions_url: + "https://api.github.com/users/ExampleOrg/subscriptions", + organizations_url: "https://api.github.com/users/ExampleOrg/orgs", + repos_url: "https://api.github.com/users/ExampleOrg/repos", + events_url: "https://api.github.com/users/ExampleOrg/events{/privacy}", + received_events_url: + "https://api.github.com/users/ExampleOrg/received_events", + type: "User", + site_admin: false, }, - html_url: 'https://github.com/ExampleOrg/github-webhook-proxy', + html_url: "https://github.com/ExampleOrg/github-webhook-proxy", description: null, fork: false, - url: 'https://github.com/ExampleOrg/github-webhook-proxy', - forks_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/forks', - keys_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/keys{/key_id}', - collaborators_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/collaborators{/collaborator}', - teams_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/teams', - hooks_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/hooks', - issue_events_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/issues/events{/number}', - events_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/events', - assignees_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/assignees{/user}', - branches_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/branches{/branch}', - tags_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/tags', - blobs_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/git/blobs{/sha}', - git_tags_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/git/tags{/sha}', - git_refs_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/git/refs{/sha}', - trees_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/git/trees{/sha}', - statuses_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/statuses/{sha}', - languages_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/languages', - stargazers_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/stargazers', - contributors_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/contributors', - subscribers_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/subscribers', - subscription_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/subscription', - commits_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/commits{/sha}', - git_commits_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/git/commits{/sha}', - comments_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/comments{/number}', - issue_comment_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/issues/comments{/number}', - contents_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/contents/{+path}', - compare_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/compare/{base}...{head}', - merges_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/merges', - archive_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/{archive_format}{/ref}', - downloads_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/downloads', - issues_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/issues{/number}', - pulls_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/pulls{/number}', - milestones_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/milestones{/number}', + url: "https://github.com/ExampleOrg/github-webhook-proxy", + forks_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/forks", + keys_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/keys{/key_id}", + collaborators_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/collaborators{/collaborator}", + teams_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/teams", + hooks_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/hooks", + issue_events_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/issues/events{/number}", + events_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/events", + assignees_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/assignees{/user}", + branches_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/branches{/branch}", + tags_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/tags", + blobs_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/git/blobs{/sha}", + git_tags_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/git/tags{/sha}", + git_refs_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/git/refs{/sha}", + trees_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/git/trees{/sha}", + statuses_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/statuses/{sha}", + languages_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/languages", + stargazers_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/stargazers", + contributors_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/contributors", + subscribers_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/subscribers", + subscription_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/subscription", + commits_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/commits{/sha}", + git_commits_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/git/commits{/sha}", + comments_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/comments{/number}", + issue_comment_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/issues/comments{/number}", + contents_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/contents/{+path}", + compare_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/compare/{base}...{head}", + merges_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/merges", + archive_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/{archive_format}{/ref}", + downloads_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/downloads", + issues_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/issues{/number}", + pulls_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/pulls{/number}", + milestones_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/milestones{/number}", notifications_url: - 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/notifications{?since,all,participating}', - labels_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/labels{/name}', - releases_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/releases{/id}', - deployments_url: 'https://api.github.com/repos/ExampleOrg/github-webhook-proxy/deployments', + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/notifications{?since,all,participating}", + labels_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/labels{/name}", + releases_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/releases{/id}", + deployments_url: + "https://api.github.com/repos/ExampleOrg/github-webhook-proxy/deployments", created_at: 1650312935, - updated_at: '2022-04-19T12:27:56Z', + updated_at: "2022-04-19T12:27:56Z", pushed_at: 1650489516, - git_url: 'git://github.com/ExampleOrg/github-webhook-proxy.git', - ssh_url: 'git@github.com:ExampleOrg/github-webhook-proxy.git', - clone_url: 'https://github.com/ExampleOrg/github-webhook-proxy.git', - svn_url: 'https://github.com/ExampleOrg/github-webhook-proxy', + git_url: "git://github.com/ExampleOrg/github-webhook-proxy.git", + ssh_url: "git@github.com:ExampleOrg/github-webhook-proxy.git", + clone_url: "https://github.com/ExampleOrg/github-webhook-proxy.git", + svn_url: "https://github.com/ExampleOrg/github-webhook-proxy", homepage: null, size: 3, stargazers_count: 0, @@ -100,108 +139,113 @@ export const VALID_PUSH_PAYLOAD: PushEvent = { is_template: false, web_commit_signoff_required: false, topics: [], - visibility: 'private', + visibility: "private", forks: 0, open_issues: 0, watchers: 0, - default_branch: 'main', + default_branch: "main", stargazers: 0, - master_branch: 'main', - has_discussions: false + master_branch: "main", + has_discussions: false, }, pusher: { - name: 'ExampleOrg', - email: 'user@ExampleOrg.com' + name: "ExampleOrg", + email: "user@ExampleOrg.com", }, organization: { - login: 'ExampleOrg', + login: "ExampleOrg", id: 102772738, - node_id: 'O_kgDOBiAwAg', - url: 'https://api.github.com/orgs/ExampleOrg', - repos_url: 'https://api.github.com/orgs/ExampleOrg/repos', - events_url: 'https://api.github.com/orgs/ExampleOrg/events', - hooks_url: 'https://api.github.com/orgs/ExampleOrg/hooks', - issues_url: 'https://api.github.com/orgs/ExampleOrg/issues', - members_url: 'https://api.github.com/orgs/ExampleOrg/members{/member}', - public_members_url: 'https://api.github.com/orgs/ExampleOrg/public_members{/member}', - avatar_url: 'https://avatars.githubusercontent.com/u/102772738?v=4', - description: null + node_id: "O_kgDOBiAwAg", + url: "https://api.github.com/orgs/ExampleOrg", + repos_url: "https://api.github.com/orgs/ExampleOrg/repos", + events_url: "https://api.github.com/orgs/ExampleOrg/events", + hooks_url: "https://api.github.com/orgs/ExampleOrg/hooks", + issues_url: "https://api.github.com/orgs/ExampleOrg/issues", + members_url: "https://api.github.com/orgs/ExampleOrg/members{/member}", + public_members_url: + "https://api.github.com/orgs/ExampleOrg/public_members{/member}", + avatar_url: "https://avatars.githubusercontent.com/u/102772738?v=4", + description: null, }, enterprise: { id: 123, - slug: 'some_enterprise', - name: 'Some Enterprise', - node_id: 'E_kgDNLDI', - avatar_url: 'https://avatars.githubusercontent.com/b/11314?v=4', + slug: "some_enterprise", + name: "Some Enterprise", + node_id: "E_kgDNLDI", + avatar_url: "https://avatars.githubusercontent.com/b/11314?v=4", description: null, website_url: null, - html_url: 'https://github.com/enterprises/some_enterprise', - created_at: '2022-01-31T20:50:21Z', - updated_at: '2022-02-03T03:52:22Z' + html_url: "https://github.com/enterprises/some_enterprise", + created_at: "2022-01-31T20:50:21Z", + updated_at: "2022-02-03T03:52:22Z", }, sender: { - login: 'ExampleOrg', + login: "ExampleOrg", id: 103291641, - node_id: 'U_kgDOBiga-Q', - avatar_url: 'https://avatars.githubusercontent.com/u/103291641?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/ExampleOrg', - html_url: 'https://github.com/ExampleOrg', - followers_url: 'https://api.github.com/users/ExampleOrg/followers', - following_url: 'https://api.github.com/users/ExampleOrg/following{/other_user}', - gists_url: 'https://api.github.com/users/ExampleOrg/gists{/gist_id}', - starred_url: 'https://api.github.com/users/ExampleOrg/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/ExampleOrg/subscriptions', - organizations_url: 'https://api.github.com/users/ExampleOrg/orgs', - repos_url: 'https://api.github.com/users/ExampleOrg/repos', - events_url: 'https://api.github.com/users/ExampleOrg/events{/privacy}', - received_events_url: 'https://api.github.com/users/ExampleOrg/received_events', - type: 'User', - site_admin: false + node_id: "U_kgDOBiga-Q", + avatar_url: "https://avatars.githubusercontent.com/u/103291641?v=4", + gravatar_id: "", + url: "https://api.github.com/users/ExampleOrg", + html_url: "https://github.com/ExampleOrg", + followers_url: "https://api.github.com/users/ExampleOrg/followers", + following_url: + "https://api.github.com/users/ExampleOrg/following{/other_user}", + gists_url: "https://api.github.com/users/ExampleOrg/gists{/gist_id}", + starred_url: + "https://api.github.com/users/ExampleOrg/starred{/owner}{/repo}", + subscriptions_url: "https://api.github.com/users/ExampleOrg/subscriptions", + organizations_url: "https://api.github.com/users/ExampleOrg/orgs", + repos_url: "https://api.github.com/users/ExampleOrg/repos", + events_url: "https://api.github.com/users/ExampleOrg/events{/privacy}", + received_events_url: + "https://api.github.com/users/ExampleOrg/received_events", + type: "User", + site_admin: false, }, created: false, deleted: false, forced: false, base_ref: null, - compare: 'https://github.com/ExampleOrg/github-webhook-proxy/compare/448223ee31c5...7119b388e221', + compare: + "https://github.com/ExampleOrg/github-webhook-proxy/compare/448223ee31c5...7119b388e221", commits: [ { - id: '7119b388e221a96ced5e1dfa0528d51847828308', - tree_id: 'e5d86be93b96d8389e85e1e34560e936786e6ec2', + id: "7119b388e221a96ced5e1dfa0528d51847828308", + tree_id: "e5d86be93b96d8389e85e1e34560e936786e6ec2", distinct: true, - message: 'dummy commit', - timestamp: '2022-04-20T17:18:32-04:00', - url: 'https://github.com/ExampleOrg/github-webhook-proxy/commit/7119b388e221a96ced5e1dfa0528d51847828308', + message: "dummy commit", + timestamp: "2022-04-20T17:18:32-04:00", + url: "https://github.com/ExampleOrg/github-webhook-proxy/commit/7119b388e221a96ced5e1dfa0528d51847828308", author: { - name: 'user', - email: 'user@ExampleOrg.com' + name: "user", + email: "user@ExampleOrg.com", }, committer: { - name: 'user', - email: 'user@ExampleOrg.com' + name: "user", + email: "user@ExampleOrg.com", }, added: [], removed: [], - modified: [] - } + modified: [], + }, ], head_commit: { - id: '7119b388e221a96ced5e1dfa0528d51847828308', - tree_id: 'e5d86be93b96d8389e85e1e34560e936786e6ec2', + id: "7119b388e221a96ced5e1dfa0528d51847828308", + tree_id: "e5d86be93b96d8389e85e1e34560e936786e6ec2", distinct: true, - message: 'dummy commit', - timestamp: '2022-04-20T17:18:32-04:00', - url: 'https://github.com/ExampleOrg/github-webhook-proxy/commit/7119b388e221a96ced5e1dfa0528d51847828308', + message: "dummy commit", + timestamp: "2022-04-20T17:18:32-04:00", + url: "https://github.com/ExampleOrg/github-webhook-proxy/commit/7119b388e221a96ced5e1dfa0528d51847828308", author: { - name: 'user', - email: 'user@ExampleOrg.com' + name: "user", + email: "user@ExampleOrg.com", }, committer: { - name: 'user', - email: 'user@ExampleOrg.com' + name: "user", + email: "user@ExampleOrg.com", }, added: [], removed: [], - modified: [] - } + modified: [], + }, }; diff --git a/lambda/destination-host-is-allowed.ts b/lambda/destination-host-is-allowed.ts index dc85a9e..73bcffe 100644 --- a/lambda/destination-host-is-allowed.ts +++ b/lambda/destination-host-is-allowed.ts @@ -11,19 +11,27 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { readFileFromLayer } from './file-readers'; -import { isMatch } from 'micromatch'; +import { readFileFromLayer } from "./file-readers"; +import micromatch from "micromatch"; export function destinationHostIsAllowed(url: string) { - const allowedDestinationHostsContents = readFileFromLayer('allowed-destination-hosts.json'); + const allowedDestinationHostsContents = readFileFromLayer( + "allowed-destination-hosts.json", + ); if (!allowedDestinationHostsContents) { return true; } - const allowedDestinationHosts: string[] = JSON.parse(allowedDestinationHostsContents); + const allowedDestinationHosts: string[] = JSON.parse( + allowedDestinationHostsContents, + ); const host = new URL(url).host; - const destinationHostIsAllowed = allowedDestinationHosts.includes(host) || isMatch(host, allowedDestinationHosts); + const destinationHostIsAllowed = + allowedDestinationHosts.includes(host) || + micromatch.isMatch(host, allowedDestinationHosts); if (!destinationHostIsAllowed) { - console.error(`Destination host ${host} does not match allowlist ${allowedDestinationHosts}`); + console.error( + `Destination host ${host} does not match allowlist ${allowedDestinationHosts}`, + ); } return destinationHostIsAllowed; } diff --git a/lambda/file-readers.ts b/lambda/file-readers.ts index dfc21d7..883051f 100644 --- a/lambda/file-readers.ts +++ b/lambda/file-readers.ts @@ -11,7 +11,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { existsSync, readFileSync } from 'fs'; +import { existsSync, readFileSync } from "fs"; export function readFileFromLayer(fileName: string) { const filePath = `/opt/layer/${fileName}`; @@ -23,5 +23,5 @@ export function readFileFromLayer(fileName: string) { } export function getPublicCerts() { - return readFileSync('build/public-certs.pem').toString(); + return readFileSync("build/public-certs.pem").toString(); } diff --git a/lambda/get-https-agent.ts b/lambda/get-https-agent.ts index 49d208c..6b1d258 100644 --- a/lambda/get-https-agent.ts +++ b/lambda/get-https-agent.ts @@ -11,18 +11,18 @@ See the License for the specific language governing permissions and limitations under the License. */ -import https from 'https'; -import { getPublicCerts, readFileFromLayer } from './file-readers'; +import https from "https"; +import { getPublicCerts, readFileFromLayer } from "./file-readers"; export function getHttpsAgent() { - const suppliedCertificateAuthority = readFileFromLayer('ca.pem'); - const suppliedCertificate = readFileFromLayer('cert.pem'); + const suppliedCertificateAuthority = readFileFromLayer("ca.pem"); + const suppliedCertificate = readFileFromLayer("cert.pem"); if (!suppliedCertificateAuthority || !suppliedCertificate) { return undefined; } return new https.Agent({ - ca: [getPublicCerts(), suppliedCertificateAuthority].join('\n'), - cert: suppliedCertificate + ca: [getPublicCerts(), suppliedCertificateAuthority].join("\n"), + cert: suppliedCertificate, }); } diff --git a/lambda/parse-request-body.ts b/lambda/parse-request-body.ts index c048290..08b9ac5 100644 --- a/lambda/parse-request-body.ts +++ b/lambda/parse-request-body.ts @@ -11,18 +11,28 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { IncomingHttpHeaders } from 'http'; -import { parse } from 'query-string'; -import { bodySchema, CONTENT_TYPES, headersSchema } from './schema'; +import { IncomingHttpHeaders } from "http"; +import { bodySchema, CONTENT_TYPES, headersSchema } from "./schema"; +import { EnterpriseProxyEvent } from "./types"; -export function parseRequestBody(body: string, headers: IncomingHttpHeaders) { +export function parseRequestBody( + body: string, + headers: IncomingHttpHeaders, +): EnterpriseProxyEvent | undefined { const headersResult = headersSchema.parse(headers); - const contentType = headersResult['content-type']; - switch (contentType) { - case CONTENT_TYPES.JSON: - return JSON.parse(body); - case CONTENT_TYPES.URL_ENCODED: - const { payload } = bodySchema.parse(parse(body)); - return JSON.parse(decodeURIComponent(payload)); + const contentType = headersResult["content-type"]; + try { + switch (contentType) { + case CONTENT_TYPES.JSON: + return JSON.parse(body); + case CONTENT_TYPES.URL_ENCODED: + const params = new URLSearchParams(body); + const payloadParam = params.get("payload"); + const { payload } = bodySchema.parse(payloadParam); + return JSON.parse(decodeURIComponent(payload)); + } + } catch (error) { + console.error(`Error parsing request body: ${error}`); + return undefined; } } diff --git a/lambda/proxy.test.ts b/lambda/proxy.test.ts index 554b9a5..8e912f0 100644 --- a/lambda/proxy.test.ts +++ b/lambda/proxy.test.ts @@ -11,280 +11,300 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { handler } from './proxy'; -import axios, { AxiosRequestHeaders, AxiosResponse } from 'axios'; -import { readFileSync } from 'fs'; -import { Agent } from 'https'; -import { readFileFromLayer } from './file-readers'; -import { APIGatewayProxyWithLambdaAuthorizerEvent } from 'aws-lambda'; -import { VALID_PING_EVENT } from '../fixtures/valid-ping-payload'; -import { VALID_PUSH_PAYLOAD } from '../fixtures/valid-push-payload'; -import { VALID_PUSH_PAYLOAD_USER_REPO } from '../fixtures/valid-push-payload-user-repo'; -const urlencodedPayload = readFileSync('fixtures/invalid-payload-urlencoded.txt').toString(); +import { handler } from "./proxy"; +import axios, { AxiosRequestHeaders, AxiosResponse } from "axios"; +import { readFileSync } from "fs"; +import { Agent } from "https"; +import { readFileFromLayer } from "./file-readers"; +import { APIGatewayProxyWithLambdaAuthorizerEvent } from "aws-lambda"; +import { VALID_PING_EVENT } from "../fixtures/valid-ping-payload"; +import { VALID_PUSH_PAYLOAD } from "../fixtures/valid-push-payload"; +import { VALID_PUSH_PAYLOAD_USER_REPO } from "../fixtures/valid-push-payload-user-repo"; +const urlencodedPayload = readFileSync( + "fixtures/invalid-payload-urlencoded.txt", +).toString(); -jest.mock('axios'); -jest.mock('./file-readers'); +jest.mock("axios"); +jest.mock("./file-readers"); const axiosResponse: AxiosResponse = { status: 200, data: { - some: 'data' + some: "data", }, headers: { - response: 'headers' + response: "headers", }, - statusText: 'status', + statusText: "status", config: { - headers: {} as AxiosRequestHeaders - } + headers: {} as AxiosRequestHeaders, + }, }; (axios.post as jest.Mock).mockResolvedValue(axiosResponse); const expectedResponseObject = { statusCode: 200, body: '{"some":"data"}', - headers: { response: 'headers' } + headers: { response: "headers" }, }; const stringifiedPayload = JSON.stringify(VALID_PUSH_PAYLOAD); const baseEvent: APIGatewayProxyWithLambdaAuthorizerEvent = { body: stringifiedPayload, headers: { - Accept: '*/*', - 'content-type': 'application/json', - Host: 'some-api.us-west-2.amazonaws.com' + Accept: "*/*", + "content-type": "application/json", + Host: "some-api.us-west-2.amazonaws.com", }, pathParameters: { - endpointId: encodeURIComponent('https://approved.host/github-webhook/') + endpointId: encodeURIComponent("https://approved.host/github-webhook/"), }, multiValueHeaders: {}, - httpMethod: 'POST', + httpMethod: "POST", isBase64Encoded: false, - path: '', + path: "", queryStringParameters: {}, multiValueQueryStringParameters: {}, stageVariables: {}, requestContext: {} as any, - resource: '' + resource: "", }; const fileMap: Record = { - 'allowed-destination-hosts.json': JSON.stringify(['approved.host', 'another.approved.host', 'a.wildcard.*.host']) + "allowed-destination-hosts.json": JSON.stringify([ + "approved.host", + "another.approved.host", + "a.wildcard.*.host", + ]), }; -(readFileFromLayer as jest.Mock).mockImplementation((fileName: string) => fileMap[fileName]); +(readFileFromLayer as jest.Mock).mockImplementation( + (fileName: string) => fileMap[fileName], +); -describe('proxy', () => { +describe("proxy", () => { beforeEach(() => { - process.env.ENTERPRISE_SLUG = 'some_enterprise'; - process.env.ENTERPRISE_MANAGED_USER_SUFFIX = ''; + process.env.ENTERPRISE_SLUG = "some_enterprise"; + process.env.ENTERPRISE_MANAGED_USER_SUFFIX = ""; }); - it('should reject a request with an invalid urlencoded payload', async () => { + it("should reject a request with an invalid urlencoded payload", async () => { const event: APIGatewayProxyWithLambdaAuthorizerEvent = { ...baseEvent, headers: { ...baseEvent.headers, - 'content-type': 'application/x-www-form-urlencoded' + "content-type": "application/x-www-form-urlencoded", }, - body: urlencodedPayload + body: urlencodedPayload, }; const result = await handler(event); - expect(result).toEqual({ statusCode: 403, body: 'Access denied' }); + expect(result).toEqual({ statusCode: 403, body: "Access denied" }); expect(axios.post).not.toHaveBeenCalled(); }); - it('should reject a request with an endpointId which is not an encoded URL', async () => { + it("should reject a request with an endpointId which is not an encoded URL", async () => { const event: APIGatewayProxyWithLambdaAuthorizerEvent = { ...baseEvent, pathParameters: { - endpointId: 'some-invalid-endpoint' - } + endpointId: "some-invalid-endpoint", + }, }; const result = await handler(event); - expect(result).toEqual({ statusCode: 403, body: 'Access denied' }); + expect(result).toEqual({ statusCode: 403, body: "Access denied" }); expect(axios.post).not.toHaveBeenCalled(); }); - it('should allow a request from a managed user suffix when supplied', async () => { - process.env.ENTERPRISE_MANAGED_USER_SUFFIX = 'suffix'; - const destinationUrl = 'https://approved.host/github-webhook/'; + it("should allow a request from a managed user suffix when supplied", async () => { + process.env.ENTERPRISE_MANAGED_USER_SUFFIX = "suffix"; + const destinationUrl = "https://approved.host/github-webhook/"; const endpointId = encodeURIComponent(destinationUrl); const event: APIGatewayProxyWithLambdaAuthorizerEvent = { ...baseEvent, body: JSON.stringify(VALID_PUSH_PAYLOAD_USER_REPO), pathParameters: { - endpointId - } + endpointId, + }, }; const result = await handler(event); expect(result).toEqual(expectedResponseObject); expect(axios.post).toHaveBeenCalled(); }); - it('should forward a request when header is Content-Type', async () => { - const destinationUrl = 'https://approved.host/github-webhook/'; + it("should forward a request when header is Content-Type", async () => { + const destinationUrl = "https://approved.host/github-webhook/"; const endpointId = encodeURIComponent(destinationUrl); const event: APIGatewayProxyWithLambdaAuthorizerEvent = { ...baseEvent, headers: { - Accept: '*/*', - 'Content-Type': 'application/json', - Host: 'some-api.us-west-2.amazonaws.com' + Accept: "*/*", + "Content-Type": "application/json", + Host: "some-api.us-west-2.amazonaws.com", }, body: JSON.stringify(VALID_PUSH_PAYLOAD), pathParameters: { - endpointId - } + endpointId, + }, }; const result = await handler(event); expect(result).toEqual(expectedResponseObject); expect(axios.post).toHaveBeenCalled(); }); - it('should not forward a request that does not come from an enterprise or managed user suffix', async () => { - const destinationUrl = 'https://approved.host/github-webhook/'; + it("should not forward a request that does not come from an enterprise or managed user suffix", async () => { + const destinationUrl = "https://approved.host/github-webhook/"; const endpointId = encodeURIComponent(destinationUrl); const payload = { ...VALID_PUSH_PAYLOAD, - enterprise: undefined + enterprise: undefined, }; const event: APIGatewayProxyWithLambdaAuthorizerEvent = { ...baseEvent, body: JSON.stringify(payload), pathParameters: { - endpointId - } + endpointId, + }, }; const result = await handler(event); - expect(result).toEqual({ statusCode: 403, body: 'Access denied' }); + expect(result).toEqual({ statusCode: 403, body: "Access denied" }); expect(axios.post).not.toHaveBeenCalled(); }); - it('should not forward a request that does not have an approved host', async () => { - const destinationUrl = 'https://not-an-approved.host/github-webhook/'; + it("should not forward a request that does not have an approved host", async () => { + const destinationUrl = "https://not-an-approved.host/github-webhook/"; const endpointId = encodeURIComponent(destinationUrl); const event: APIGatewayProxyWithLambdaAuthorizerEvent = { ...baseEvent, pathParameters: { - endpointId - } + endpointId, + }, }; const result = await handler(event); - expect(result).toEqual({ statusCode: 403, body: 'Access denied' }); + expect(result).toEqual({ statusCode: 403, body: "Access denied" }); expect(axios.post).not.toHaveBeenCalled(); }); - it('should forward a request that has an approved host which matches a wildcard', async () => { - const destinationUrl = 'https://a.wildcard.test.host/github-webhook/'; + it("should forward a request that has an approved host which matches a wildcard", async () => { + const destinationUrl = "https://a.wildcard.test.host/github-webhook/"; const endpointId = encodeURIComponent(destinationUrl); const event: APIGatewayProxyWithLambdaAuthorizerEvent = { ...baseEvent, pathParameters: { - endpointId - } + endpointId, + }, }; const result = await handler(event); expect(result).toEqual(expectedResponseObject); }); - it('should forward a request from an enterprise and github org without supplied certs', async () => { - const destinationUrl = 'https://approved.host/github-webhook/'; + it("should forward a request from an enterprise and github org without supplied certs", async () => { + const destinationUrl = "https://approved.host/github-webhook/"; const endpointId = encodeURIComponent(destinationUrl); const event: APIGatewayProxyWithLambdaAuthorizerEvent = { ...baseEvent, pathParameters: { - endpointId - } + endpointId, + }, }; const result = await handler(event); - expect(axios.post).toHaveBeenCalledWith(destinationUrl, stringifiedPayload, { - headers: { - Accept: '*/*', - 'content-type': 'application/json' - } - }); + expect(axios.post).toHaveBeenCalledWith( + destinationUrl, + stringifiedPayload, + { + headers: { + Accept: "*/*", + "content-type": "application/json", + }, + }, + ); expect(result).toEqual(expectedResponseObject); }); - it('should forward a request from an enterprise and github org with supplied certs', async () => { + it("should forward a request from an enterprise and github org with supplied certs", async () => { const newFileMap: Record = { ...fileMap, - 'ca.pem': 'some ca', - 'cert.pem': 'some cert' + "ca.pem": "some ca", + "cert.pem": "some cert", }; - (readFileFromLayer as jest.Mock).mockImplementation((fileName: string) => newFileMap[fileName]); - const destinationUrl = 'https://approved.host/github-webhook/'; + (readFileFromLayer as jest.Mock).mockImplementation( + (fileName: string) => newFileMap[fileName], + ); + const destinationUrl = "https://approved.host/github-webhook/"; const endpointId = encodeURIComponent(destinationUrl); const event: APIGatewayProxyWithLambdaAuthorizerEvent = { ...baseEvent, pathParameters: { - endpointId - } + endpointId, + }, }; const result = await handler(event); - expect(axios.post).toHaveBeenCalledWith(destinationUrl, stringifiedPayload, { - headers: { - Accept: '*/*', - 'content-type': 'application/json' + expect(axios.post).toHaveBeenCalledWith( + destinationUrl, + stringifiedPayload, + { + headers: { + Accept: "*/*", + "content-type": "application/json", + }, + httpsAgent: expect.any(Agent), }, - httpsAgent: expect.any(Agent) - }); + ); expect(result).toEqual(expectedResponseObject); }); - it('should return a 404 when no endpointId is found', async () => { + it("should return a 404 when no endpointId is found", async () => { const event: APIGatewayProxyWithLambdaAuthorizerEvent = { ...baseEvent, - pathParameters: {} + pathParameters: {}, }; const result = await handler(event); - expect(result).toEqual({ statusCode: 404, body: 'Not found' }); + expect(result).toEqual({ statusCode: 404, body: "Not found" }); expect(axios.post).not.toHaveBeenCalled(); }); - it('should forward a ping event from a managed user suffix when supplied', async () => { - process.env.ENTERPRISE_MANAGED_USER_SUFFIX = 'suffix'; - const destinationUrl = 'https://approved.host/github-webhook/'; + it("should forward a ping event from a managed user suffix when supplied", async () => { + process.env.ENTERPRISE_MANAGED_USER_SUFFIX = "suffix"; + const destinationUrl = "https://approved.host/github-webhook/"; const endpointId = encodeURIComponent(destinationUrl); const event: APIGatewayProxyWithLambdaAuthorizerEvent = { ...baseEvent, body: JSON.stringify(VALID_PING_EVENT), pathParameters: { - endpointId - } + endpointId, + }, }; const result = await handler(event); expect(result).toEqual(expectedResponseObject); expect(axios.post).toHaveBeenCalled(); }); - it('should return error response from axios', async () => { + it("should return error response from axios", async () => { const axiosErrorResponse: AxiosResponse = { status: 400, data: { - some: 'error' + some: "error", }, headers: { - response: 'headers' + response: "headers", }, - statusText: 'bad request', + statusText: "bad request", config: { - headers: {} as AxiosRequestHeaders - } + headers: {} as AxiosRequestHeaders, + }, }; - (axios.post as jest.Mock).mockRejectedValue({ response: axiosErrorResponse }); + (axios.post as jest.Mock).mockRejectedValue({ + response: axiosErrorResponse, + }); - process.env.ENTERPRISE_MANAGED_USER_SUFFIX = 'suffix'; - const destinationUrl = 'https://approved.host/github-webhook/'; + process.env.ENTERPRISE_MANAGED_USER_SUFFIX = "suffix"; + const destinationUrl = "https://approved.host/github-webhook/"; const endpointId = encodeURIComponent(destinationUrl); const event: APIGatewayProxyWithLambdaAuthorizerEvent = { ...baseEvent, body: JSON.stringify(VALID_PUSH_PAYLOAD_USER_REPO), pathParameters: { - endpointId - } + endpointId, + }, }; const result = await handler(event); expect(result).toEqual({ statusCode: 400, body: '{"some":"error"}', - headers: { response: 'headers' } + headers: { response: "headers" }, }); expect(axios.post).toHaveBeenCalled(); }); diff --git a/lambda/proxy.ts b/lambda/proxy.ts index 9e495e8..00b3212 100644 --- a/lambda/proxy.ts +++ b/lambda/proxy.ts @@ -11,57 +11,79 @@ See the License for the specific language governing permissions and limitations under the License. */ -import axios, { AxiosResponse } from 'axios'; -import { APIGatewayProxyWithLambdaAuthorizerEvent } from 'aws-lambda'; -import { requestPayloadIsValid } from './request-payload-is-valid'; -import { destinationHostIsAllowed } from './destination-host-is-allowed'; -import { getHttpsAgent } from './get-https-agent'; -import { parseRequestBody } from './parse-request-body'; -import { EnterpriseProxyEvent } from './types'; -import { urlIsValid } from './url-is-valid'; -import { axiosErrorSchema } from './schema'; +import axios, { AxiosResponse } from "axios"; +import { APIGatewayProxyWithLambdaAuthorizerEvent } from "aws-lambda"; +import { requestPayloadIsValid } from "./request-payload-is-valid"; +import { destinationHostIsAllowed } from "./destination-host-is-allowed"; +import { getHttpsAgent } from "./get-https-agent"; +import { parseRequestBody } from "./parse-request-body"; +import { EnterpriseProxyEvent } from "./types"; +import { urlIsValid } from "./url-is-valid"; +import { axiosErrorSchema } from "./schema"; -export async function handler(event: APIGatewayProxyWithLambdaAuthorizerEvent) { +export async function handler( + event: APIGatewayProxyWithLambdaAuthorizerEvent, +) { try { - console.info('Incoming event:', JSON.stringify(event)); + console.info("Incoming event:", JSON.stringify(event)); const { body, headers, pathParameters } = event; const endpointId = pathParameters?.endpointId; if (!endpointId || !body) { - console.error(`EndpointId or body is missing. endpointId: ${endpointId}, body: ${body}`); - return { statusCode: 404, body: 'Not found' }; + console.error( + `EndpointId or body is missing. endpointId: ${endpointId}, body: ${body}`, + ); + return { statusCode: 404, body: "Not found" }; } - const requestPayload: EnterpriseProxyEvent = parseRequestBody(body, headers); + const requestPayload = parseRequestBody(body, headers); const url = decodeURIComponent(endpointId); - if (!urlIsValid(url) || !requestPayloadIsValid(requestPayload) || !destinationHostIsAllowed(url)) { - return { statusCode: 403, body: 'Access denied' }; + if ( + !urlIsValid(url) || + !requestPayloadIsValid(requestPayload) || + !destinationHostIsAllowed(url) + ) { + return { statusCode: 403, body: "Access denied" }; } // Forward all headers except `Host` - delete headers['Host']; + delete headers["Host"]; - console.info('Forwarding webhook for url:', url); + console.info("Forwarding webhook for url:", url); const { status: statusCode, data, - headers: responseHeaders + headers: responseHeaders, } = await axios.post(url, body, { headers, httpsAgent: getHttpsAgent() }); - console.info('Request was forwarded successfully!'); - console.info('result', JSON.stringify({ statusCode, body: data, headers: responseHeaders })); + console.info("Request was forwarded successfully!"); + console.info( + "result", + JSON.stringify({ statusCode, body: data, headers: responseHeaders }), + ); return { statusCode, body: JSON.stringify(data), headers: responseHeaders }; } catch (error) { const safeError = axiosErrorSchema.safeParse(error); if (safeError.success) { - console.warn('Request was forwarded but got an error response.'); - const { status: statusCode, data, headers: responseHeaders } = safeError.data.response as AxiosResponse; - console.warn('result', JSON.stringify({ statusCode, body: data, headers: responseHeaders })); - return { statusCode, body: JSON.stringify(data), headers: responseHeaders }; + console.warn("Request was forwarded but got an error response."); + const { + status: statusCode, + data, + headers: responseHeaders, + } = safeError.data.response as AxiosResponse; + console.warn( + "result", + JSON.stringify({ statusCode, body: data, headers: responseHeaders }), + ); + return { + statusCode, + body: JSON.stringify(data), + headers: responseHeaders, + }; } - console.error('An unknown error occurred.', error); + console.error("An unknown error occurred.", error); return { statusCode: 500, body: `Internal server error: ${error}` }; } } diff --git a/lambda/request-payload-is-valid.ts b/lambda/request-payload-is-valid.ts index 59749b5..38b822f 100644 --- a/lambda/request-payload-is-valid.ts +++ b/lambda/request-payload-is-valid.ts @@ -11,18 +11,25 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { EnterpriseProxyEvent } from './types'; +import { EnterpriseProxyEvent } from "./types"; -export function requestPayloadIsValid({ sender, enterprise }: EnterpriseProxyEvent) { - return requestCameFromValidEnterprise(enterprise) || senderLoginEndsWithUserSuffix(sender?.login); +export function requestPayloadIsValid(payload?: EnterpriseProxyEvent) { + const { sender, enterprise } = payload ?? {}; + return ( + requestCameFromValidEnterprise(enterprise) || + senderLoginEndsWithUserSuffix(sender?.login) + ); } -function requestCameFromValidEnterprise(enterprise?: EnterpriseProxyEvent['enterprise']) { +function requestCameFromValidEnterprise( + enterprise?: EnterpriseProxyEvent["enterprise"], +) { const requestCameFromValidEnterprise = - process.env.ENTERPRISE_SLUG && enterprise?.slug === process.env.ENTERPRISE_SLUG; + process.env.ENTERPRISE_SLUG && + enterprise?.slug === process.env.ENTERPRISE_SLUG; if (!requestCameFromValidEnterprise) { console.error( - `ENTERPRISE_SLUG environment variable ${process.env.ENTERPRISE_SLUG} does not equal enterprise slug ${enterprise?.slug}` + `ENTERPRISE_SLUG environment variable ${process.env.ENTERPRISE_SLUG} does not equal enterprise slug ${enterprise?.slug}`, ); } return requestCameFromValidEnterprise; @@ -34,7 +41,7 @@ function senderLoginEndsWithUserSuffix(senderLogin?: string) { senderLogin?.endsWith(`_${process.env.ENTERPRISE_MANAGED_USER_SUFFIX}`); if (!senderLoginEndsWithUserSuffix) { console.error( - `Sender login ${senderLogin} does not end with ENTERPRISE_MANAGED_USER_SUFFIX environment variable ${process.env.ENTERPRISE_MANAGED_USER_SUFFIX}` + `Sender login ${senderLogin} does not end with ENTERPRISE_MANAGED_USER_SUFFIX environment variable ${process.env.ENTERPRISE_MANAGED_USER_SUFFIX}`, ); } return senderLoginEndsWithUserSuffix; diff --git a/lambda/schema.ts b/lambda/schema.ts index 67d6e6d..4cb5914 100644 --- a/lambda/schema.ts +++ b/lambda/schema.ts @@ -1,32 +1,32 @@ -import { z } from 'zod'; -import mapKeys from 'lodash.mapkeys'; +import { z } from "zod"; +import mapKeys from "lodash.mapkeys"; export const urlSchema = z.string().url(); export const bodySchema = z.object({ - payload: z.string() + payload: z.string(), }); export const CONTENT_TYPES = { - JSON: 'application/json', - URL_ENCODED: 'application/x-www-form-urlencoded' + JSON: "application/json", + URL_ENCODED: "application/x-www-form-urlencoded", } as const; export const headersSchema = z.preprocess( - obj => { - if (obj && typeof obj == 'object') { + (obj) => { + if (obj && typeof obj == "object") { return mapKeys(obj, (_, key) => key.toLowerCase()); } }, z.object({ - 'content-type': z.nativeEnum(CONTENT_TYPES) - }) + "content-type": z.nativeEnum(CONTENT_TYPES), + }), ); export const axiosErrorSchema = z.object({ response: z.object({ status: z.number(), headers: z.any(), - data: z.any() - }) + data: z.any(), + }), }); diff --git a/lambda/types.ts b/lambda/types.ts index 49221f6..8156197 100644 --- a/lambda/types.ts +++ b/lambda/types.ts @@ -1,7 +1,9 @@ -import { components } from '@octokit/openapi-types'; +import { components } from "@octokit/openapi-types"; -export type EnterprisePayload = { enterprise?: components['schemas']['enterprise'] }; -export type PingEvent = components['schemas']['webhook-ping']; -export type PushEvent = components['schemas']['webhook-push']; +export type EnterprisePayload = { + enterprise?: components["schemas"]["enterprise"]; +}; +export type PingEvent = components["schemas"]["webhook-ping"]; +export type PushEvent = components["schemas"]["webhook-push"]; export type EnterpriseProxyEvent = (PushEvent | PingEvent) & EnterprisePayload; diff --git a/lambda/url-is-valid.ts b/lambda/url-is-valid.ts index bb6599f..c32d018 100644 --- a/lambda/url-is-valid.ts +++ b/lambda/url-is-valid.ts @@ -1,9 +1,9 @@ -import { urlSchema } from './schema'; +import { urlSchema } from "./schema"; export function urlIsValid(url: string) { const urlIsValid = urlSchema.safeParse(url).success; if (!urlIsValid) { - console.error('Invalid URL:', url); + console.error("Invalid URL:", url); } return urlIsValid; } diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 4de190d..0000000 --- a/package-lock.json +++ /dev/null @@ -1,4225 +0,0 @@ -{ - "name": "github-webhook-proxy", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "github-webhook-proxy", - "dependencies": { - "axios": "1.6.8", - "lodash.mapkeys": "4.6.0", - "query-string": "7.1.3", - "zod": "3.22.4" - }, - "devDependencies": { - "@octokit/webhooks": "13.2.4", - "@swc/jest": "0.2.36", - "@types/aws-lambda": "8.10.137", - "@types/jest": "29.5.12", - "@types/lodash.mapkeys": "4.6.9", - "@types/micromatch": "4.0.7", - "@types/node": "20.12.7", - "jest": "29.7.0", - "prettier": "3.2.5", - "typescript": "5.4.5" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "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==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/code-frame/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/code-frame/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/code-frame/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "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==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.20.tgz", - "integrity": "sha512-Y6jd1ahLubuYweD/zJH+vvOY141v4f9igNQAQ+MBgq9JlHS2iTsZKn1aMsb3vGccZsXI16VzTBw52Xx0DWmtnA==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.22.15", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.22.20", - "@babel/helpers": "^7.22.15", - "@babel/parser": "^7.22.16", - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.22.20", - "@babel/types": "^7.22.19", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/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/@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==", - "dev": true, - "dependencies": { - "@babel/types": "^7.23.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "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==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.15", - "browserslist": "^4.21.9", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.15" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.20.tgz", - "integrity": "sha512-dLT7JVWIUUxKOs1UnJUBR3S70YK+pKX6AbJgB2vMIvEkZkrfJDbYDJesnPshtKV4LhDOR3Oc5YULeDizRek+5A==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "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==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "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==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.15.tgz", - "integrity": "sha512-7pAjK0aSdxOwR+CcYAqgWOGy5dcfvzsTIfFTb2odQqW47MDfv14UaJDY6eng8ylM2EaeKXdxaSWESbkmaQHTmw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.22.15", - "@babel/types": "^7.22.15" - }, - "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==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "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==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@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", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "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==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", - "dev": true, - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/create-cache-key-function": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", - "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "dev": true, - "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", - "dev": true, - "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", - "dev": true, - "dependencies": { - "jest-get-type": "^29.6.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", - "dev": true, - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", - "dev": true, - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", - "dev": true, - "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "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==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@octokit/openapi-types": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", - "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", - "dev": true - }, - "node_modules/@octokit/openapi-webhooks-types": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@octokit/openapi-webhooks-types/-/openapi-webhooks-types-8.1.1.tgz", - "integrity": "sha512-cfavqtPS5W1vy2JGXODIL4LsoXYoaXIhiNbil53wb9sLsTFuSBl+r1L6nNiVq/Ie8j0MSB2rCAGrGKJTfjqVEw==", - "dev": true - }, - "node_modules/@octokit/request-error": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.0.1.tgz", - "integrity": "sha512-EPeILOAEGqwmEG6g7dYlbvqkjJ5nWNcZvQpgeLEn1MieIcJ0xK0CJtvVcIMXqzIM8DOWzvI6zL5FQAwjTvk/Tg==", - "dev": true, - "dependencies": { - "@octokit/types": "^12.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/types": { - "version": "12.6.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", - "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", - "dev": true, - "dependencies": { - "@octokit/openapi-types": "^20.0.0" - } - }, - "node_modules/@octokit/webhooks": { - "version": "13.2.4", - "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-13.2.4.tgz", - "integrity": "sha512-nvjEW4ncfXGABPjLTgjXJrLNpMJRe8K+EZPxuwczZLbRjxMU2NJhGxAEWJXWBW5ziMlqanDr10QBX75dDpuqLQ==", - "dev": true, - "dependencies": { - "@octokit/openapi-webhooks-types": "8.1.1", - "@octokit/request-error": "^6.0.1", - "@octokit/webhooks-methods": "^5.0.0", - "aggregate-error": "^5.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/webhooks-methods": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@octokit/webhooks-methods/-/webhooks-methods-5.0.0.tgz", - "integrity": "sha512-bMypz/oiU4DqaujqZH7IOwMyrHfr2MBZbXqrttyR/kawne7t8CIv1k+xALazo6VCuE7DJZbgBG1RFdk5OH8lnw==", - "dev": true, - "engines": { - "node": ">= 18" - } - }, - "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/@swc/core": { - "version": "1.3.61", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.61.tgz", - "integrity": "sha512-p58Ltdjo7Yy8CU3zK0cp4/eAgy5qkHs35znGedqVGPiA67cuYZM63DuTfmyrOntMRwQnaFkMLklDAPCizDdDng==", - "dev": true, - "hasInstallScript": true, - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/swc" - }, - "optionalDependencies": { - "@swc/core-darwin-arm64": "1.3.61", - "@swc/core-darwin-x64": "1.3.61", - "@swc/core-linux-arm-gnueabihf": "1.3.61", - "@swc/core-linux-arm64-gnu": "1.3.61", - "@swc/core-linux-arm64-musl": "1.3.61", - "@swc/core-linux-x64-gnu": "1.3.61", - "@swc/core-linux-x64-musl": "1.3.61", - "@swc/core-win32-arm64-msvc": "1.3.61", - "@swc/core-win32-ia32-msvc": "1.3.61", - "@swc/core-win32-x64-msvc": "1.3.61" - }, - "peerDependencies": { - "@swc/helpers": "^0.5.0" - }, - "peerDependenciesMeta": { - "@swc/helpers": { - "optional": true - } - } - }, - "node_modules/@swc/core-darwin-arm64": { - "version": "1.3.61", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.61.tgz", - "integrity": "sha512-Ra1CZIYYyIp/Y64VcKyaLjIPUwT83JmGduvHu8vhUZOvWV4dWL4s5DrcxQVaQJjjb7Z2N/IUYYS55US1TGnxZw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-darwin-x64": { - "version": "1.3.61", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.61.tgz", - "integrity": "sha512-LUia75UByUFkYH1Ddw7IE0X9usNVGJ7aL6+cgOTju7P0dsU0f8h/OGc/GDfp1E4qnKxDCJE+GwDRLoi4SjIxpg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.3.61", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.61.tgz", - "integrity": "sha512-aalPlicYxHAn2PxNlo3JFEZkMXzCtUwjP27AgMqnfV4cSz7Omo56OtC+413e/kGyCH86Er9gJRQQsxNKP8Qbsg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.3.61", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.61.tgz", - "integrity": "sha512-9hGdsbQrYNPo1c7YzWF57yl17bsIuuEQi3I1fOFSv3puL3l5M/C/oCD0Bz6IdKh6mEDC5UNJE4LWtV1gFA995A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.3.61", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.61.tgz", - "integrity": "sha512-mVmcNfFQRP4SYbGC08IPB3B9Xox+VpGIQqA3Qg7LMCcejLAQLi4Lfe8CDvvBPlQzXHso0Cv+BicJnQVKs8JLOA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.3.61", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.61.tgz", - "integrity": "sha512-ZkRHs7GEikN6JiVL1/stvq9BVHKrSKoRn9ulVK2hMr+mAGNOKm3Y06NSzOO+BWwMaFOgnO2dWlszCUICsQ0kpg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-musl": { - "version": "1.3.61", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.61.tgz", - "integrity": "sha512-zK7VqQ5JlK20+7fxI4AgvIUckeZyX0XIbliGXNMR3i+39SJq1vs9scYEmq8VnAfvNdMU5BG+DewbFJlMfCtkxQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.3.61", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.61.tgz", - "integrity": "sha512-e9kVVPk5iVNhO41TvLvcExDHn5iATQ5/M4U7/CdcC7s0fK19TKSEUqkdoTLIJvHBFhgR7w3JJSErfnauO0xXoA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.3.61", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.61.tgz", - "integrity": "sha512-7cJULfa6HvKqvFh6M/f7mKiNRhE2AjgFUCZfdOuy5r8vbtpk+qBK94TXwaDjJYDUGKzDVZw/tJ1eN4Y9n9Ls/Q==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.3.61", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.61.tgz", - "integrity": "sha512-Jx8S+21WcKF/wlhW+sYpystWUyymDTEsbBpOgBRpXZelakVcNBCIIYSZOKW/A9PwWTpu6S8yvbs9nUOzKiVPqA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/counter": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", - "dev": true - }, - "node_modules/@swc/jest": { - "version": "0.2.36", - "resolved": "https://registry.npmjs.org/@swc/jest/-/jest-0.2.36.tgz", - "integrity": "sha512-8X80dp81ugxs4a11z1ka43FPhP+/e+mJNXJSxiNYk8gIX/jPBtY4gQTrKu/KIoco8bzKuPI5lUxjfLiGsfvnlw==", - "dev": true, - "dependencies": { - "@jest/create-cache-key-function": "^29.7.0", - "@swc/counter": "^0.1.3", - "jsonc-parser": "^3.2.0" - }, - "engines": { - "npm": ">= 7.0.0" - }, - "peerDependencies": { - "@swc/core": "*" - } - }, - "node_modules/@types/aws-lambda": { - "version": "8.10.137", - "resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.137.tgz", - "integrity": "sha512-YNFwzVarXAOXkjuFxONyDw1vgRNzyH8AuyN19s0bM+ChSu/bzxb5XPxYFLXoqoM+tvgzwR3k7fXcEOW125yJxg==", - "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==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "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==", - "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==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "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==", - "dev": true, - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/braces": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/braces/-/braces-3.0.4.tgz", - "integrity": "sha512-0WR3b8eaISjEW7RpZnclONaLFDf7buaowRHdqLp4vLj54AsSAYWfh3DRbfiYJY9XDxMgx1B4sE1Afw2PGpuHOA==", - "dev": true - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", - "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", - "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==", - "dev": true - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dev": true, - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/jest": { - "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", - "pretty-format": "^29.0.0" - } - }, - "node_modules/@types/lodash": { - "version": "4.14.201", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.201.tgz", - "integrity": "sha512-y9euML0cim1JrykNxADLfaG0FgD1g/yTHwUs/Jg9ZIU7WKj2/4IW9Lbb1WZbvck78W/lfGXFfe+u2EGfIJXdLQ==", - "dev": true - }, - "node_modules/@types/lodash.mapkeys": { - "version": "4.6.9", - "resolved": "https://registry.npmjs.org/@types/lodash.mapkeys/-/lodash.mapkeys-4.6.9.tgz", - "integrity": "sha512-6/ERBCabeDI656LsV+oopLjdnJ/x1PCAE6kkkssH8e4i0K7Pw307noxHCbUc6cAVfTo9vx0Z+k3QZwy1IrUZcA==", - "dev": true, - "dependencies": { - "@types/lodash": "*" - } - }, - "node_modules/@types/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@types/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-C/FMQ8HJAZhTsDpl4wDKZdMeeW5USjgzOczUwTGbRc1ZopPgOhIEnxY2ZgUrsuyy4DwK1JVOJZKFakv3TbCKiA==", - "dev": true, - "dependencies": { - "@types/braces": "*" - } - }, - "node_modules/@types/node": { - "version": "20.12.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", - "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", - "dev": true, - "dependencies": { - "undici-types": "~5.26.4" - } - }, - "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/yargs": { - "version": "17.0.24", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", - "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", - "dev": true, - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", - "dev": true - }, - "node_modules/aggregate-error": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-5.0.0.tgz", - "integrity": "sha512-gOsf2YwSlleG6IjRYG2A7k0HmBMEo6qVNk9Bp/EaLgAJT5ngH6PXbqa4ItvnEwCm/velL5jAnQgsHsWnjhGmvw==", - "dev": true, - "dependencies": { - "clean-stack": "^5.2.0", - "indent-string": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/axios": { - "version": "1.6.8", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", - "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "dev": true, - "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "dev": true, - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dev": true, - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", - "dev": true, - "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "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/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.21.10", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", - "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001517", - "electron-to-chromium": "^1.4.477", - "node-releases": "^2.0.13", - "update-browserslist-db": "^1.0.11" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "dependencies": { - "node-int64": "^0.4.0" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001535", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001535.tgz", - "integrity": "sha512-48jLyUkiWFfhm/afF7cQPqPjaUmSraEhK4j+FCTJpgnGGEZHqyLe3hmWH7lIooZdSzXL0ReMvHz0vKDoTBsrwg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, - "node_modules/cjs-module-lexer": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", - "dev": true - }, - "node_modules/clean-stack": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-5.2.0.tgz", - "integrity": "sha512-TyUIUJgdFnCISzG5zu3291TAsE77ddchd0bepon1VVQrKLGKFED4iXFEDQ24mIPdPBbyE16PK3F8MYE1CmcBEQ==", - "dev": true, - "dependencies": { - "escape-string-regexp": "5.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/clean-stack/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true, - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "dev": true - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/create-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" - }, - "bin": { - "create-jest": "bin/create-jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/dedent": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", - "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", - "dev": true, - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.523", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.523.tgz", - "integrity": "sha512-9AreocSUWnzNtvLcbpng6N+GkXnCcBR80IQkxRC9Dfdyg4gaWNUPBujAHUpKkiUkoSoR9UlhA4zD/IgBklmhzg==", - "dev": true - }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", - "dev": true, - "dependencies": { - "@jest/expect-utils": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, - "dependencies": { - "bser": "2.1.1" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/filter-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", - "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "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 - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/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-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", - "dev": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "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==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "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==", - "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==", - "dev": true, - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-instrument/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/istanbul-lib-instrument/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-instrument/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/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", - "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", - "dev": true, - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-changed-files": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", - "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", - "dev": true, - "dependencies": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-circus": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", - "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.7.0", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.7.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-cli": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", - "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", - "dev": true, - "dependencies": { - "@jest/core": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "create-jest": "^29.7.0", - "exit": "^0.1.2", - "import-local": "^3.0.2", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-config": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-circus": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "micromatch": "^4.0.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-docblock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", - "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", - "dev": true, - "dependencies": { - "detect-newline": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-each": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", - "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, - "node_modules/jest-leak-detector": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", - "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", - "dev": true, - "dependencies": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "dev": true, - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } - } - }, - "node_modules/jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", - "dev": true, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", - "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve-dependencies": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", - "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", - "dev": true, - "dependencies": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runner": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", - "dev": true, - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/environment": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-leak-detector": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-resolve": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-util": "^29.7.0", - "jest-watcher": "^29.7.0", - "jest-worker": "^29.7.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runtime": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", - "dev": true, - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-snapshot": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", - "dev": true, - "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-snapshot/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/jest-snapshot/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jest-snapshot/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/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", - "dev": true, - "dependencies": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-watcher": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", - "dev": true, - "dependencies": { - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", - "dev": true - }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash.mapkeys": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.mapkeys/-/lodash.mapkeys-4.6.0.tgz", - "integrity": "sha512-0Al+hxpYvONWtg+ZqHpa/GaVzxuN3V7Xeo2p+bY06EaK/n+Y9R7nBePPN2o1LxmL0TWQSwP8LYZ008/hc9JzhA==" - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/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/make-dir/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-dir/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/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "dependencies": { - "tmpl": "1.0.5" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "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/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "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==", - "dev": true - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/prettier": { - "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" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "node_modules/pure-rand": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.3.tgz", - "integrity": "sha512-KddyFewCsO0j3+np81IQ+SweXLDnDQTs5s67BOnrYmYe/yNmUhttQyGsYzy8yUnoljGAQ9sl38YB4vH8ur7Y+w==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ] - }, - "node_modules/query-string": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz", - "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==", - "dependencies": { - "decode-uri-component": "^0.2.2", - "filter-obj": "^1.1.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.6", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz", - "integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==", - "dev": true, - "dependencies": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/split-on-first": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", - "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/strict-uri-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", - "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "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==", - "dev": true - }, - "node_modules/update-browserslist-db": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", - "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "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==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.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/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "dependencies": { - "makeerror": "1.0.12" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "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/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/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/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zod": { - "version": "3.22.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", - "integrity": "sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - } - } -} diff --git a/package.json b/package.json index 896a6e5..4de14a5 100644 --- a/package.json +++ b/package.json @@ -1,26 +1,26 @@ { "name": "github-webhook-proxy", + "packageManager": "bun@1.1.4", "main": "lambdas/proxy/index.js", + "type": "module", "scripts": { - "build": "tsc", - "format": "prettier --write ./**/*.ts", - "format-check": "prettier --check **/*.ts", - "test": "jest --silent" + "build": "bun build lambda/proxy.ts --outdir build/ --target node", + "format": "prettier --write .", + "format-check": "prettier --check", + "test": "bun jest" }, "dependencies": { "axios": "1.6.8", "lodash.mapkeys": "4.6.0", - "query-string": "7.1.3", - "zod": "3.22.4" + "zod": "3.23.3" }, "devDependencies": { - "@octokit/webhooks": "13.2.4", + "@octokit/webhooks": "13.2.5", "@swc/jest": "0.2.36", "@types/aws-lambda": "8.10.137", "@types/jest": "29.5.12", "@types/lodash.mapkeys": "4.6.9", "@types/micromatch": "4.0.7", - "@types/node": "20.12.7", "jest": "29.7.0", "prettier": "3.2.5", "typescript": "5.4.5" @@ -29,6 +29,12 @@ "transform": { "^.+\\.(t|j)sx?$": "@swc/jest" }, + "moduleNameMapper": { + "^(\\.{1,2}/.*)\\.js$": "$1" + }, + "extensionsToTreatAsEsm": [ + ".ts" + ], "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$", "clearMocks": true } diff --git a/tsconfig.json b/tsconfig.json index 507d3c7..6e48cbc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,22 +1,17 @@ { "compilerOptions": { - "outDir": "build", - "lib": ["esnext", "dom", "dom.iterable"], - "module": "commonjs", - "target": "es5", - "sourceMap": true, - "esModuleInterop": true, - "jsx": "react", + "allowSyntheticDefaultImports": true, + "moduleDetection": "force", "moduleResolution": "node", + "module": "esnext", + "target": "esnext", + "types": ["jest", "node"], + "noEmit": true, + "noImplicitAny": true, + "noUncheckedIndexedAccess": true, "resolveJsonModule": true, + "skipLibCheck": true, "strict": true }, - "include": [ - "lambda" - ], - "exclude": [ - "node_modules", - "github-ip-ranges", - "**/*.test.ts" - ] + "exclude": ["build"] }