diff --git a/source/infrastructure/.eslintrc.js b/.eslintrc.js
similarity index 88%
rename from source/infrastructure/.eslintrc.js
rename to .eslintrc.js
index c1996674..16cda2f5 100644
--- a/source/infrastructure/.eslintrc.js
+++ b/.eslintrc.js
@@ -7,7 +7,7 @@ module.exports = {
es2021: true,
},
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:prettier/recommended"],
- ignorePatterns: [".eslintrc.js"],
+ ignorePatterns: [".eslintrc.js", "coverage/", "deployment/coverage-reports/"],
overrides: [],
parserOptions: {
ecmaVersion: "latest",
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..1e538ece
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,18 @@
+# ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen".
+
+*.snap linguist-generated
+/.gitattributes linguist-generated
+/.github/pull_request_template.md linguist-generated
+/.gitignore linguist-generated
+/.npmrc linguist-generated
+/.projen/** linguist-generated
+/.projen/deps.json linguist-generated
+/.projen/files.json linguist-generated
+/.projen/jest-snapshot-resolver.js linguist-generated
+/.projen/tasks.json linguist-generated
+/cdk.json linguist-generated
+/jest.config.json linguist-generated
+/LICENSE linguist-generated
+/package-lock.json linguist-generated
+/package.json linguist-generated
+/tsconfig.json linguist-generated
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 00000000..4aa3ae8e
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,41 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ""
+labels: bug
+assignees: ""
+---
+
+**Describe the bug**
+
+
+
+**To Reproduce**
+
+
+
+**Expected behavior**
+
+
+
+**Please complete the following information about the solution:**
+
+- [ ] Version: [e.g. v1.0.0]
+
+To get the version of the solution, you can look at the description of the created CloudFormation stack. For example,
+_"(SO0030) instance-scheduler-on-aws v1.5.1"_. You can also find the version from
+[releases](https://github.com/aws-solutions/instance-scheduler-on-aws/releases)
+
+- [ ] Region: [e.g. us-east-1]
+- [ ] Was the solution modified from the version published on this repository?
+- [ ] If the answer to the previous question was yes, are the changes available on GitHub?
+- [ ] Have you checked your [service quotas](https://docs.aws.amazon.com/general/latest/gr/aws_service_limits.html) for
+ the sevices this solution uses?
+- [ ] Were there any errors in the CloudWatch Logs?
+ [Troubleshooting](https://docs.aws.amazon.com/solutions/latest/instance-scheduler-on-aws/troubleshooting.html)
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem (please **DO NOT include sensitive information**).
+
+**Additional context**
+Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 00000000..05364d35
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,19 @@
+---
+name: Feature request
+about: Suggest an idea for this solution
+title: ""
+labels: feature-request, enhancement
+assignees: ""
+---
+
+**Is your feature request related to a problem? Please describe.**
+
+
+
+**Describe the feature you'd like**
+
+
+
+**Additional context**
+
+
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 00000000..74a7a79a
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,6 @@
+_Issue #, if available:_
+
+_Description of changes:_
+
+By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the
+terms of your choice.
diff --git a/.gitignore b/.gitignore
index 7fd3b0ef..36c05c8e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,18 +1,37 @@
-
-
-
-# Created by .ignore support plugin (hsz.mobi)
-### Python template
-# Byte-compiled / optimized / DLL files
+# ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen".
+!/.gitattributes
+!/.projen/tasks.json
+!/.projen/deps.json
+!/.projen/files.json
+!/package.json
+!/LICENSE
+logs
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
+pids
+*.pid
+*.seed
+*.pid.lock
+lib-cov
+coverage
+*.lcov
+.nyc_output
+build/Release
+node_modules/
+jspm_packages/
+*.tsbuildinfo
+.eslintcache
+*.tgz
+.yarn-integrity
__pycache__/
*.py[cod]
*$py.class
*node_modules*
-
-# C extensions
*.so
*.pyc
-# Distribution / packaging
.Python
env/
build/
@@ -28,21 +47,11 @@ var/
*.egg-info/
.installed.cfg
*.egg
-
-#PyCharm/Webstorm
.idea/
-
-# PyInstaller
-# Usually these files are written by a python script from a template
-# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
-
-# Installer logs
pip-log.txt
pip-delete-this-directory.txt
-
-# Unit test / coverage reports
htmlcov/
.tox/
.coverage
@@ -54,71 +63,55 @@ coverage.xml
.hypothesis/
deployment/coverage-reports/
deployment/test-reports/
-
-# Translations
+coverage/
*.mo
*.pot
-
-# Django stuff:
*.log
local_settings.py
-
-# Flask stuff:
instance/
.webassets-cache
-
-# Scrapy stuff:
.scrapy
-
-# Sphinx documentation
docs/_build/
-
-# PyBuilder
target/
-
-# IPython Notebook
.ipynb_checkpoints
-
-# pyenv
.python-version
-
-# celery beat schedule file
celerybeat-schedule
-
-# dotenv
.env
-
-# virtualenv
.venv/
venv/
ENV/
-
-# Spyder project settings
.spyderproject
-
-# Rope project settings
.ropeproject
-
-#cdk
*cdk.out*
*.js
-
-# config
!.eslintrc.js
-
-#ignore these in the deployment folder
*regional-s3-assets*
*staging*
*global-s3-assets*
.DS_Store
-
.pytest_cache
-
+.mypy_cache
*.zip
deployment/open-source
deployment/dist
source/deploy
-
source/code/sample_events
.vscode
__pycache__
+**/cdk-test-report.xml
+!/.projenrc.js
+!/jest.config.json
+/coverage/
+!/.github/pull_request_template.md
+!/.npmrc
+!/source/instance-scheduler/tests/
+!/tsconfig.json
+!/source/
+/lib
+/dist/
+!/.projen/jest-snapshot-resolver.js
+/assets/
+!/cdk.json
+/build/cdk.out/
+.cdk.staging/
+.parcel-cache/
diff --git a/source/infrastructure/.prettierrc b/.prettierrc
similarity index 100%
rename from source/infrastructure/.prettierrc
rename to .prettierrc
diff --git a/.projen/deps.json b/.projen/deps.json
new file mode 100644
index 00000000..f2894c8e
--- /dev/null
+++ b/.projen/deps.json
@@ -0,0 +1,128 @@
+{
+ "dependencies": [
+ {
+ "name": "@types/jest",
+ "type": "build"
+ },
+ {
+ "name": "@types/node",
+ "version": "^18",
+ "type": "build"
+ },
+ {
+ "name": "@typescript-eslint/eslint-plugin",
+ "type": "build"
+ },
+ {
+ "name": "aws-cdk",
+ "version": "^2.87.0",
+ "type": "build"
+ },
+ {
+ "name": "esbuild",
+ "type": "build"
+ },
+ {
+ "name": "eslint",
+ "type": "build"
+ },
+ {
+ "name": "eslint-config-prettier",
+ "type": "build"
+ },
+ {
+ "name": "eslint-plugin-header",
+ "type": "build"
+ },
+ {
+ "name": "eslint-plugin-import",
+ "type": "build"
+ },
+ {
+ "name": "eslint-plugin-prettier",
+ "type": "build"
+ },
+ {
+ "name": "jest",
+ "type": "build"
+ },
+ {
+ "name": "jest-extended",
+ "type": "build"
+ },
+ {
+ "name": "jest-junit",
+ "type": "build"
+ },
+ {
+ "name": "npm-check-updates",
+ "version": "^16",
+ "type": "build"
+ },
+ {
+ "name": "projen",
+ "type": "build"
+ },
+ {
+ "name": "ts-jest",
+ "type": "build"
+ },
+ {
+ "name": "ts-node",
+ "type": "build"
+ },
+ {
+ "name": "typescript",
+ "type": "build"
+ },
+ {
+ "name": "@aws-cdk/aws-lambda-python-alpha",
+ "version": "^2.87.0-alpha.0",
+ "type": "runtime"
+ },
+ {
+ "name": "@aws-cdk/aws-servicecatalogappregistry-alpha",
+ "version": "^2.87.0-alpha.0",
+ "type": "runtime"
+ },
+ {
+ "name": "@aws-sdk/client-dynamodb",
+ "type": "runtime"
+ },
+ {
+ "name": "@aws-sdk/client-ec2",
+ "type": "runtime"
+ },
+ {
+ "name": "@aws-sdk/client-rds",
+ "type": "runtime"
+ },
+ {
+ "name": "@aws-sdk/client-ssm",
+ "type": "runtime"
+ },
+ {
+ "name": "@aws-solutions-constructs/aws-lambda-dynamodb",
+ "type": "runtime"
+ },
+ {
+ "name": "aws-cdk-lib",
+ "version": "^2.87.0",
+ "type": "runtime"
+ },
+ {
+ "name": "cdk-nag",
+ "type": "runtime"
+ },
+ {
+ "name": "constructs",
+ "version": "^10.0.5",
+ "type": "runtime"
+ },
+ {
+ "name": "source-map-support",
+ "type": "runtime"
+ }
+ ],
+ "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"."
+}
diff --git a/.projen/files.json b/.projen/files.json
new file mode 100644
index 00000000..286f260f
--- /dev/null
+++ b/.projen/files.json
@@ -0,0 +1,17 @@
+{
+ "files": [
+ ".gitattributes",
+ ".github/pull_request_template.md",
+ ".gitignore",
+ ".npmrc",
+ ".projen/deps.json",
+ ".projen/files.json",
+ ".projen/jest-snapshot-resolver.js",
+ ".projen/tasks.json",
+ "cdk.json",
+ "jest.config.json",
+ "LICENSE",
+ "tsconfig.json"
+ ],
+ "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"."
+}
diff --git a/.projen/jest-snapshot-resolver.js b/.projen/jest-snapshot-resolver.js
new file mode 100644
index 00000000..b014f4ea
--- /dev/null
+++ b/.projen/jest-snapshot-resolver.js
@@ -0,0 +1,15 @@
+const path = require("path");
+const libtest = "lib/instance-scheduler/tests";
+const srctest= "source/instance-scheduler/tests";
+module.exports = {
+ resolveSnapshotPath: (test, ext) => {
+ const fullpath = test.replace(libtest, srctest);
+ return path.join(path.dirname(fullpath), "__snapshots__", path.basename(fullpath, ".js") + ".ts" + ext);
+ },
+ resolveTestPath: (snap, ext) => {
+ const filename = path.basename(snap, ".ts" + ext) + ".js";
+ const dir = path.dirname(path.dirname(snap)).replace(srctest, libtest);
+ return path.join(dir, filename);
+ },
+ testPathForConsistencyCheck: path.join('some', '__tests__', 'example.test.js')
+};
\ No newline at end of file
diff --git a/.projen/tasks.json b/.projen/tasks.json
new file mode 100644
index 00000000..387e0e4c
--- /dev/null
+++ b/.projen/tasks.json
@@ -0,0 +1,373 @@
+{
+ "tasks": {
+ "build": {
+ "name": "build",
+ "description": "Full release build",
+ "steps": [
+ {
+ "spawn": "default"
+ },
+ {
+ "spawn": "pre-compile"
+ },
+ {
+ "spawn": "compile"
+ },
+ {
+ "spawn": "post-compile"
+ },
+ {
+ "spawn": "test"
+ },
+ {
+ "spawn": "package"
+ }
+ ]
+ },
+ "bundle": {
+ "name": "bundle",
+ "description": "Prepare assets"
+ },
+ "clobber": {
+ "name": "clobber",
+ "description": "hard resets to HEAD of origin and cleans the local repo",
+ "env": {
+ "BRANCH": "$(git branch --show-current)"
+ },
+ "steps": [
+ {
+ "exec": "git checkout -b scratch",
+ "name": "save current HEAD in \"scratch\" branch"
+ },
+ {
+ "exec": "git checkout $BRANCH"
+ },
+ {
+ "exec": "git fetch origin",
+ "name": "fetch latest changes from origin"
+ },
+ {
+ "exec": "git reset --hard origin/$BRANCH",
+ "name": "hard reset to origin commit"
+ },
+ {
+ "exec": "git clean -fdx",
+ "name": "clean all untracked files"
+ },
+ {
+ "say": "ready to rock! (unpushed commits are under the \"scratch\" branch)"
+ }
+ ],
+ "condition": "git diff --exit-code > /dev/null"
+ },
+ "compile": {
+ "name": "compile",
+ "description": "Only compile"
+ },
+ "default": {
+ "name": "default",
+ "description": "Synthesize project files",
+ "steps": [
+ {
+ "exec": "ts-node --project tsconfig.json .projenrc.ts"
+ }
+ ]
+ },
+ "deploy": {
+ "name": "deploy",
+ "description": "Deploys your CDK app to the AWS cloud",
+ "steps": [
+ {
+ "exec": "cdk deploy",
+ "receiveArgs": true
+ }
+ ]
+ },
+ "destroy": {
+ "name": "destroy",
+ "description": "Destroys your cdk app in the AWS cloud",
+ "steps": [
+ {
+ "exec": "cdk destroy",
+ "receiveArgs": true
+ }
+ ]
+ },
+ "diff": {
+ "name": "diff",
+ "description": "Diffs the currently deployed app against your code",
+ "steps": [
+ {
+ "exec": "cdk diff"
+ }
+ ]
+ },
+ "e2e-tests": {
+ "name": "e2e-tests",
+ "steps": [
+ {
+ "exec": "jest --config source/pipeline/jest.config.ts",
+ "receiveArgs": true
+ }
+ ]
+ },
+ "eject": {
+ "name": "eject",
+ "description": "Remove projen from the project",
+ "env": {
+ "PROJEN_EJECTING": "true"
+ },
+ "steps": [
+ {
+ "spawn": "default"
+ }
+ ]
+ },
+ "install": {
+ "name": "install",
+ "description": "Install project dependencies and update lockfile (non-frozen)",
+ "steps": [
+ {
+ "exec": "npm install"
+ }
+ ]
+ },
+ "install:ci": {
+ "name": "install:ci",
+ "description": "Install project dependencies using frozen lockfile",
+ "steps": [
+ {
+ "exec": "npm ci"
+ }
+ ]
+ },
+ "package": {
+ "name": "package",
+ "description": "Creates the distribution package"
+ },
+ "post-compile": {
+ "name": "post-compile",
+ "description": "Runs after successful compilation",
+ "steps": [
+ {
+ "spawn": "synth:silent"
+ }
+ ]
+ },
+ "post-upgrade": {
+ "name": "post-upgrade",
+ "description": "Runs after upgrading dependencies"
+ },
+ "pre-compile": {
+ "name": "pre-compile",
+ "description": "Prepare the project for compilation"
+ },
+ "synth": {
+ "name": "synth",
+ "description": "Synthesizes your cdk app into cdk.out",
+ "steps": [
+ {
+ "exec": "cdk synth"
+ }
+ ]
+ },
+ "synth:silent": {
+ "name": "synth:silent",
+ "description": "Synthesizes your cdk app into cdk.out and suppresses the template in stdout (part of \"yarn build\")",
+ "steps": [
+ {
+ "exec": "cdk synth -q"
+ }
+ ]
+ },
+ "test": {
+ "name": "test",
+ "description": "Run tests",
+ "steps": [
+ {
+ "spawn": "test:prettier"
+ },
+ {
+ "spawn": "test:eslint"
+ },
+ {
+ "spawn": "test:cdk"
+ },
+ {
+ "spawn": "test:app"
+ },
+ {
+ "spawn": "test:cli"
+ }
+ ]
+ },
+ "test:app": {
+ "name": "test:app",
+ "steps": [
+ {
+ "exec": "python -m tox --parallel --exit-and-dump-after 1200"
+ }
+ ],
+ "cwd": "source/app"
+ },
+ "test:app:ci": {
+ "name": "test:app:ci",
+ "env": {
+ "TOX_PARALLEL_NO_SPINNER": "true"
+ },
+ "steps": [
+ {
+ "exec": "python -m tox --parallel --exit-and-dump-after 1200 --skip-missing-interpreters false -- --junitxml=../../deployment/test-reports/lambda-test-report.xml --cov --cov-report \"xml:../../deployment/coverage-reports/lambda-coverage.xml\" && sed -i -e \"s|||g\" ../../deployment/coverage-reports/lambda-coverage.xml"
+ }
+ ],
+ "cwd": "source/app"
+ },
+ "test:cdk": {
+ "name": "test:cdk",
+ "steps": [
+ {
+ "exec": "jest --coverageProvider=v8 --ci"
+ }
+ ]
+ },
+ "test:cdk:ci": {
+ "name": "test:cdk:ci",
+ "steps": [
+ {
+ "exec": "jest --coverageProvider=v8 --ci --coverage --coverageDirectory deployment/coverage-reports/cdk-coverage"
+ }
+ ]
+ },
+ "test:ci": {
+ "name": "test:ci",
+ "steps": [
+ {
+ "spawn": "test:prettier"
+ },
+ {
+ "spawn": "test:eslint"
+ },
+ {
+ "spawn": "test:cdk:ci"
+ },
+ {
+ "spawn": "test:app:ci"
+ },
+ {
+ "spawn": "test:cli:ci"
+ }
+ ]
+ },
+ "test:cli": {
+ "name": "test:cli",
+ "steps": [
+ {
+ "exec": "python -m tox --parallel --exit-and-dump-after 1200"
+ }
+ ],
+ "cwd": "source/cli"
+ },
+ "test:cli:ci": {
+ "name": "test:cli:ci",
+ "env": {
+ "TOX_PARALLEL_NO_SPINNER": "true"
+ },
+ "steps": [
+ {
+ "exec": "python -m tox --parallel --exit-and-dump-after 1200 --skip-missing-interpreters false -- --junitxml=../../deployment/test-reports/cli-test-report.xml --cov --cov-report \"xml:../../deployment/coverage-reports/cli-coverage.xml\" && sed -i -e \"s|||g\" ../../deployment/coverage-reports/cli-coverage.xml"
+ }
+ ],
+ "cwd": "source/cli"
+ },
+ "test:eslint": {
+ "name": "test:eslint",
+ "steps": [
+ {
+ "exec": "npx eslint --max-warnings=0 ."
+ }
+ ]
+ },
+ "test:prettier": {
+ "name": "test:prettier",
+ "steps": [
+ {
+ "exec": "npx prettier --check ./**/*.ts"
+ }
+ ]
+ },
+ "test:update": {
+ "name": "test:update",
+ "description": "Update jest snapshots",
+ "steps": [
+ {
+ "exec": "jest --updateSnapshot --passWithNoTests --coverageProvider=v8 --ci",
+ "receiveArgs": true
+ }
+ ]
+ },
+ "test:watch": {
+ "name": "test:watch",
+ "description": "Run jest in watch mode",
+ "steps": [
+ {
+ "exec": "jest --watch"
+ }
+ ]
+ },
+ "upgrade": {
+ "name": "upgrade",
+ "description": "upgrade dependencies",
+ "env": {
+ "CI": "0"
+ },
+ "steps": [
+ {
+ "exec": "npm update npm-check-updates"
+ },
+ {
+ "exec": "npm-check-updates --dep dev --upgrade --target=minor"
+ },
+ {
+ "exec": "npm-check-updates --dep optional --upgrade --target=minor"
+ },
+ {
+ "exec": "npm-check-updates --dep peer --upgrade --target=minor"
+ },
+ {
+ "exec": "npm-check-updates --dep prod --upgrade --target=minor"
+ },
+ {
+ "exec": "npm-check-updates --dep bundle --upgrade --target=minor"
+ },
+ {
+ "exec": "npm install"
+ },
+ {
+ "exec": "npm update"
+ },
+ {
+ "exec": "npx projen"
+ },
+ {
+ "spawn": "post-upgrade"
+ }
+ ]
+ },
+ "watch": {
+ "name": "watch",
+ "description": "Watches changes in your source code and rebuilds and deploys to the current account",
+ "steps": [
+ {
+ "exec": "cdk deploy --hotswap"
+ },
+ {
+ "exec": "cdk watch"
+ }
+ ]
+ }
+ },
+ "env": {
+ "PATH": "$(npx -c \"node --print process.env.PATH\")"
+ },
+ "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"."
+}
diff --git a/.projenrc.ts b/.projenrc.ts
new file mode 100644
index 00000000..d06fcb6e
--- /dev/null
+++ b/.projenrc.ts
@@ -0,0 +1,233 @@
+#!/usr/bin/env node
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+import { readFileSync } from "node:fs";
+import { awscdk } from "projen";
+import { JestReporter, NodePackageManager, Transform, UpdateSnapshot } from "projen/lib/javascript";
+
+const cdkVersion = "2.87.0";
+const solutionId = "SO0030";
+const solutionName = "instance-scheduler-on-aws";
+
+const project = new awscdk.AwsCdkTypeScriptApp({
+ projenrcTs: true,
+ minNodeVersion: "18.0.0",
+ name: "instance-scheduler-on-aws",
+ description: `Instance Scheduler on AWS (${solutionId})`,
+ authorName: "Amazon Web Services",
+ authorUrl: "https://aws.amazon.com/solutions",
+ authorOrganization: true,
+ defaultReleaseBranch: "main",
+ packageManager: NodePackageManager.NPM,
+ majorVersion: 1,
+ srcdir: "source",
+ testdir: "source/instance-scheduler/tests",
+ cdkVersion,
+ cdkout: "build/cdk.out",
+ appEntrypoint: "instance-scheduler.ts",
+ jestOptions: {
+ configFilePath: "jest.config.json",
+ updateSnapshot: UpdateSnapshot.NEVER,
+ junitReporting: false, // we will override
+ jestConfig: {
+ roots: ["/source/instance-scheduler/tests"],
+ transform: { "^.+\\.tsx?$": new Transform("ts-jest") },
+ reporters: [
+ new JestReporter("jest-junit", {
+ outputDirectory: "deployment/test-reports",
+ outputName: "cdk-test-report.xml",
+ }),
+ ],
+ },
+ },
+ context: {
+ solutionId,
+ solutionName,
+ appRegApplicationName: "AWS-Solutions",
+ appRegSolutionName: solutionName,
+ "instance-scheduler-on-aws-pipeline-source": "codecommit",
+ },
+ deps: [
+ `@aws-cdk/aws-lambda-python-alpha@^${cdkVersion}-alpha.0`,
+ `@aws-cdk/aws-servicecatalogappregistry-alpha@^${cdkVersion}-alpha.0`,
+ "@aws-sdk/client-dynamodb",
+ "@aws-sdk/client-ec2",
+ "@aws-sdk/client-rds",
+ "@aws-sdk/client-ssm",
+ "@aws-solutions-constructs/aws-lambda-dynamodb",
+ "cdk-nag",
+ "constructs",
+ "source-map-support",
+ ],
+ devDeps: [
+ "@types/jest",
+ "@types/node",
+ "@typescript-eslint/eslint-plugin",
+ "eslint",
+ "eslint-config-prettier",
+ "eslint-plugin-header",
+ "eslint-plugin-import",
+ "eslint-plugin-prettier",
+ "jest-extended",
+ "jest-junit",
+ "ts-jest",
+ ],
+ githubOptions: {
+ workflows: false,
+ },
+ pullRequestTemplateContents: readFileSync("projenrc/PULL_REQUEST_TEMPLATE.md").toString().split("\n"),
+ eslint: false,
+ autoMerge: false,
+ npmignoreEnabled: false,
+ license: "Apache-2.0",
+ disableTsconfigDev: true,
+ tsconfig: {
+ compilerOptions: {
+ rootDir: ".",
+ noUnusedLocals: true,
+ forceConsistentCasingInFileNames: true,
+ lib: ["es2022", "dom"],
+ noEmitOnError: true,
+ noPropertyAccessFromIndexSignature: false, // TODO: enable
+ noUncheckedIndexedAccess: false, // TODO: enable
+ target: "ES2022",
+ allowJs: false,
+ outDir: "build/cdk.ts.dist",
+ },
+ include: ["source/pipeline/**/*.ts", "deployment/cdk-solution-helper/**/*.ts"],
+ exclude: ["node_modules"],
+ },
+ gitignore: [
+ "__pycache__/",
+ "*.py[cod]",
+ "*$py.class",
+ "*node_modules*",
+ "*.so",
+ "*.pyc",
+ ".Python",
+ "env/",
+ "build/",
+ "develop-eggs/",
+ "dist/",
+ "downloads/",
+ "eggs/",
+ ".eggs/",
+ "lib64/",
+ "parts/",
+ "sdist/",
+ "var/",
+ "*.egg-info/",
+ ".installed.cfg",
+ "*.egg",
+ ".idea/",
+ "*.manifest",
+ "*.spec",
+ "pip-log.txt",
+ "pip-delete-this-directory.txt",
+ "htmlcov/",
+ ".tox/",
+ ".coverage",
+ ".coverage.*",
+ ".cache",
+ "nosetests.xml",
+ "coverage.xml",
+ "*,cover",
+ ".hypothesis/",
+ "deployment/coverage-reports/",
+ "deployment/test-reports/",
+ "coverage/",
+ "*.mo",
+ "*.pot",
+ "*.log",
+ "local_settings.py",
+ "instance/",
+ ".webassets-cache",
+ ".scrapy",
+ "docs/_build/",
+ "target/",
+ ".ipynb_checkpoints",
+ ".python-version",
+ "celerybeat-schedule",
+ ".env",
+ ".venv/",
+ "venv/",
+ "ENV/",
+ ".spyderproject",
+ ".ropeproject",
+ "*cdk.out*",
+ "*.js",
+ "!.eslintrc.js",
+ "*regional-s3-assets*",
+ "*staging*",
+ "*global-s3-assets*",
+ ".DS_Store",
+ ".pytest_cache",
+ ".mypy_cache",
+ "*.zip",
+ "deployment/open-source",
+ "deployment/dist",
+ "source/deploy",
+ "source/code/sample_events",
+ ".vscode",
+ "__pycache__",
+ "**/cdk-test-report.xml",
+ ],
+});
+
+project.addTask("e2e-tests", { exec: "jest --config source/pipeline/jest.config.ts", receiveArgs: true });
+
+const prettierTask = project.addTask("test:prettier", { exec: "npx prettier --check ./**/*.ts" });
+const eslintTask = project.addTask("test:eslint", { exec: "npx eslint --max-warnings=0 ." });
+const cdkTestTask = project.addTask("test:cdk", {
+ exec: "jest --coverageProvider=v8 --ci",
+});
+const appTestTask = project.addTask("test:app", {
+ cwd: "source/app",
+ exec: "python -m tox --parallel --exit-and-dump-after 1200",
+});
+const cliTestTask = project.addTask("test:cli", {
+ cwd: "source/cli",
+ exec: "python -m tox --parallel --exit-and-dump-after 1200",
+});
+
+const testTask = project.tasks.tryFind("test");
+testTask?.reset();
+testTask?.spawn(prettierTask);
+testTask?.spawn(eslintTask);
+testTask?.spawn(cdkTestTask);
+testTask?.spawn(appTestTask);
+testTask?.spawn(cliTestTask);
+
+const testCiTask = project.addTask("test:ci");
+
+const cdkTestCiTask = project.addTask("test:cdk:ci", {
+ exec: "jest --coverageProvider=v8 --ci --coverage --coverageDirectory deployment/coverage-reports/cdk-coverage",
+});
+const appTestCiTask = project.addTask("test:app:ci", {
+ cwd: "source/app",
+ env: { TOX_PARALLEL_NO_SPINNER: "true" },
+ exec: 'python -m tox --parallel --exit-and-dump-after 1200 --skip-missing-interpreters false -- --junitxml=../../deployment/test-reports/lambda-test-report.xml --cov --cov-report "xml:../../deployment/coverage-reports/lambda-coverage.xml" && sed -i -e "s|||g" ../../deployment/coverage-reports/lambda-coverage.xml',
+});
+const cliTestCiTask = project.addTask("test:cli:ci", {
+ cwd: "source/cli",
+ env: { TOX_PARALLEL_NO_SPINNER: "true" },
+ exec: 'python -m tox --parallel --exit-and-dump-after 1200 --skip-missing-interpreters false -- --junitxml=../../deployment/test-reports/cli-test-report.xml --cov --cov-report "xml:../../deployment/coverage-reports/cli-coverage.xml" && sed -i -e "s|||g" ../../deployment/coverage-reports/cli-coverage.xml',
+});
+
+testCiTask.spawn(prettierTask);
+testCiTask.spawn(eslintTask);
+testCiTask.spawn(cdkTestCiTask);
+testCiTask.spawn(appTestCiTask);
+testCiTask.spawn(cliTestCiTask);
+
+project.tryFindObjectFile("tsconfig.json")?.addOverride("files", ["global.d.ts"]);
+
+// adding to project props doesn't seem to work as expected
+project.jest?.addTestMatch("**/*.test.ts");
+
+// use default snapshot resolution
+project.tryFindObjectFile("jest.config.json")?.addOverride("snapshotResolver", undefined);
+
+project.tryFindObjectFile("package.json")?.addOverride("version", "1.5.1");
+
+project.synth();
diff --git a/.viperlightignore b/.viperlightignore
index 475f2c18..cd6d9f7e 100644
--- a/.viperlightignore
+++ b/.viperlightignore
@@ -1,9 +1,12 @@
-# Ignore Config used with code.amazon.com
-Config
+.tox/
+.mypy_cache/
+.venv/
+node_modules/
+build/cdk.out/
-^docs/
-^viperlight/
-source/app/instance_scheduler/requesthandlers/setup_demo_data.py:55
-deployment/buildspecs/mainline-s3-spec.yml:20
+source/app/instance_scheduler/handler/setup_demo_data.py:59
CODE_OF_CONDUCT.md:4
CONTRIBUTING.md:51
+
+[node-npmoutdated]
+@types/node=18.0.0
diff --git a/.viperlightrc b/.viperlightrc
index 34036e5a..0419e749 100644
--- a/.viperlightrc
+++ b/.viperlightrc
@@ -1,4 +1,4 @@
{
"all": true,
- "failOn": "medium"
+ "failOn": "high"
}
diff --git a/CHANGELOG.md b/CHANGELOG.md
old mode 100755
new mode 100644
index ec7cfb9b..94f6c2ad
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,56 +1,116 @@
# Change Log
+
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [1.5.1] - 2023-07-24
+
+### Changed
+
+- Add a default start and stop tag
+- Use EC2 API more efficiently when filtering EC2 instances for scheduling
+- Use system tzdata instead of pytz
+- Upgrade Python runtime to 3.10
+- Package CLI as sdist and wheel
+- Refactoring, type hinting, and improved testing
+- Add projen for managing project configuration
+
+### Fixed
+
+- Restore Python 3.8 support to CLI
+- Fix bug starting EC2 instances at least 10 minutes before maintenance windows
+- Fix bug targeting RDS instances that are part of an Aurora cluster for scheduling
+- Fix bug where EC2 instances failing to start or stop cause an entire batch to fail to start or stop
+- Fix bug where the instance type field on a period in a CloudFormation schedule has no effect
+- Fix bug creating CloudWatch log streams when hub scheduling is disabled
+
+### Security
+
+- Upgrade cryptography to mitigate CVE-2023-38325 and CVE-2023-2650
+- Upgrade aws-cdk-lib to mitigate CVE-2023-35165
+- Upgrade fast-xml-parser to mitigate CVE-2023-34104
+- Upgrade requests to mitigate CVE-2023-32681
+- Upgrade word-wrap to mitigate CVE-2023-26115
+- Upgrade semver to mitigate CVE-2022-25883
+
## [1.5.0] - 2023-04-27
+
### Added
+
- Enable solution to support deployment using organization id.
- Lambda code is organized with tox.
-- Development/e2e testing pipeline included under source/infrastructure/pipeline capable of automatically deploying and testing solution.
+- Development/e2e testing pipeline included under source/infrastructure/pipeline capable of automatically deploying and
+ testing solution.
- App Registry integration
+
### Fixed
+
- Boto Retry module could cause unintended high lambda utilization in case of API failures.
- Cross account scheduling no longer requires IAM role name but only account id.
## [1.4.2] - 2023-01-11
+
### Fixed
+
- Upgrade certifi to mitigate [CVE-2022-23491](https://nvd.nist.gov/vuln/detail/CVE-2022-23491).
- Updated issues in bandit scan.
- Updated the CDK version 2.x
## [1.4.1] - 2022-05-12
+
### Fixed
-- Replaced the DescribeLogStreams API call used for getting the next sequence token with PutLogEvents API call to reduce the lambda execution time [#307](https://github.com/awslabs/aws-instance-scheduler/issues/307)
+
+- Replaced the DescribeLogStreams API call used for getting the next sequence token with PutLogEvents API call to reduce
+ the lambda execution time [#307](https://github.com/aws-solutions/instance-scheduler-on-aws/issues/307)
## [1.4.0] - 2021-04-26
+
### Added
+
- Enable solution to be deployed as mutliple stacks in the same account/region
+
### Fixed
-- Fix the SSM Maintenance window issue where solution was not fetching SSM Maintenance windows from other account/regions
+
+- Fix the SSM Maintenance window issue where solution was not fetching SSM Maintenance windows from other
+ account/regions
- Updated logging utility to remove incorrect timestamp
-- Fixed issue with scheduler stopping instances at UTC time even when configured with other timezones and Period having weekday configured as Wed#4. [Github Issue](https://github.com/awslabs/aws-instance-scheduler/issues/238)
+- Fixed issue with scheduler stopping instances at UTC time even when configured with other timezones and Period having
+ weekday configured as Wed#4. [Github Issue](https://github.com/aws-solutions/instance-scheduler-on-aws/issues/238)
- Modified Anonymous Data reporting refer implementation guide for details.
- Removed redundant logging of UTC timestamp along with the Account/Region default stamp in logs in AWS CloudWatch.
-- Fixed [Github Issue](https://github.com/awslabs/aws-instance-scheduler/issues/184) for scheduler-cli.
+- Fixed [Github Issue](https://github.com/aws-solutions/instance-scheduler-on-aws/issues/184) for scheduler-cli.
## [1.3.3] - 2020-08-31
+
### Fixed
+
- Update the project to utilize aws cdk constructs for cloudformation template creation.
-- Fix the issue for ensuring throttling is avoided to cloudwatch API's from github PR [#177](https://github.com/awslabs/aws-instance-scheduler/pull/177)
+- Fix the issue for ensuring throttling is avoided to cloudwatch API's from github PR
+ [#177](https://github.com/aws-solutions/instance-scheduler-on-aws/pull/177)
+
## [1.3.2] - 2020-06-22
+
### Fixed
-- Fix the issue to start instances before the SSM maintenance window beings [#101](https://github.com/awslabs/aws-instance-scheduler/issues/101)
-- Updated the SSM feature to reduce lambda cost
-- Added HIBERNATE to the list of valid schedule properties
+- Fix the issue to start instances before the SSM maintenance window beings
+ [#101](https://github.com/aws-solutions/instance-scheduler-on-aws/issues/101)
+- Updated the SSM feature to reduce lambda cost
+- Added HIBERNATE to the list of valid schedule properties
## [1.3.1] - 2020-03-10
+
### Fixed
-- Fix the issue for new instances launched outside of the schedule period [#127](https://github.com/awslabs/aws-instance-scheduler/issues/127)
-- Fix the issue for retries failures to due incompatible code [#133](https://github.com/awslabs/aws-instance-scheduler/issues/133)
-- Fix the issue for instances being stopped after maintenance window begins [#101](https://github.com/awslabs/aws-instance-scheduler/issues/101)
+
+- Fix the issue for new instances launched outside of the schedule period
+ [#127](https://github.com/aws-solutions/instance-scheduler-on-aws/issues/127)
+- Fix the issue for retries failures to due incompatible code
+ [#133](https://github.com/aws-solutions/instance-scheduler-on-aws/issues/133)
+- Fix the issue for instances being stopped after maintenance window begins
+ [#101](https://github.com/aws-solutions/instance-scheduler-on-aws/issues/101)
## [1.3.0] - 2019-08-26
+
### Added
+
- Upgraded the Solution to Python 3.7
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
old mode 100755
new mode 100644
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
old mode 100755
new mode 100644
index a95c15c6..17512a6a
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,36 +1,39 @@
# Contributing Guidelines
-Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional
-documentation, we greatly value feedback and contributions from our community.
+Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or
+additional documentation, we greatly value feedback and contributions from our community.
Please read through this document before submitting any issues or pull requests to ensure we have all the necessary
information to effectively respond to your bug report or contribution.
-
## Reporting Bugs/Feature Requests
We welcome you to use the GitHub issue tracker to report bugs or suggest features.
-When filing an issue, please check [existing open](https://github.com/awslabs/aws-instance-scheduler-cdk/issues), or [recently closed](https://github.com/awslabs/aws-instance-scheduler-cdk/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already
-reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
-
-* A reproducible test case or series of steps
-* The version of our code being used
-* Any modifications you've made relevant to the bug
-* Anything unusual about your environment or deployment
+When filing an issue, please check [existing open](https://github.com/aws-solutions/instance-scheduler-on-aws/issues),
+or [recently closed](https://github.com/aws-solutions/instance-scheduler-on-aws/issues?q=is%3Aissue+is%3Aclosed), issues
+to make sure somebody else hasn't already reported the issue. Please try to include as much information as you can.
+Details like these are incredibly useful:
+- A reproducible test case or series of steps
+- The version of our code being used
+- Any modifications you've made relevant to the bug
+- Anything unusual about your environment or deployment
## Contributing via Pull Requests
+
Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that:
-1. You are working against the latest source on the *master* branch.
-2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already.
+1. You are working against the latest source on the _master_ branch.
+2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem
+ already.
3. You open an issue to discuss any significant work - we would hate for your time to be wasted.
To send us a pull request, please:
1. Fork the repository.
-2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change.
+2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it
+ will be hard for us to focus on your change.
3. Ensure all build processes execute successfully (see README.md for additional guidance).
4. Ensure all unit, integration, and/or snapshot tests pass, as applicable.
5. Commit to your fork using clear commit messages.
@@ -40,23 +43,29 @@ To send us a pull request, please:
GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
[creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
-
## Finding contributions to work on
-Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels ((enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/awslabs/aws-instance-scheduler-cdk/labels/help%20wanted) issues is a great place to start.
+Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the
+default GitHub issue labels ((enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help
+wanted'](https://github.com/aws-solutions/instance-scheduler-on-aws/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22)
+issues is a great place to start.
## Code of Conduct
-This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
-For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
-opensource-codeofconduct@amazon.com with any additional questions or comments.
+This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). For more
+information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
+opensource-codeofconduct@amazon.com with any additional questions or comments.
## Security issue notifications
-If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public GitHub issue.
+If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our
+[vulnerability reporting page](https://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a
+public GitHub issue.
## Licensing
-See the [LICENSE](https://github.com/awslabs/aws-instance-scheduler-cdk/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution.
+See the [LICENSE](./LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your
+contribution.
-We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes.
+We may ask you to sign a [Contributor License Agreement
+(CLA)](https://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes.
diff --git a/LICENSE.txt b/LICENSE
old mode 100755
new mode 100644
similarity index 89%
rename from LICENSE.txt
rename to LICENSE
index 19dc35b2..d6456956
--- a/LICENSE.txt
+++ b/LICENSE
@@ -172,4 +172,31 @@
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
\ No newline at end of file
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/NOTICE.txt b/NOTICE.txt
old mode 100755
new mode 100644
index 2e8a6eeb..64cb1170
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -1,6 +1,6 @@
-AWS Instance Scheduler V2
+Instance Scheduler on AWS
-Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
Licensed under the Apache License Version 2.0 (the "License"). You may not use this file except
in compliance with the License. A copy of the License is located at http://www.apache.org/licenses/
or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS,
@@ -12,7 +12,37 @@ THIRD PARTY COMPONENTS
**********************
This software includes third party software subject to the following copyrights:
-AWS SDK under the Apache License Version 2.0
-pytz under the Massachusetts Institute of Technology (MIT) license
-freezegun under the Apache License Version 2.0
-adm-zip under the Massachusetts Institute of Technology (MIT) license
+@aws-cdk/aws-lambda-python-alpha under the Apache License 2.0
+@aws-cdk/aws-servicecatalogappregistry-alpha under the Apache License 2.0
+@aws-sdk/client-dynamodb under the Apache License 2.0
+@aws-sdk/client-ec2 under the Apache License 2.0
+@aws-sdk/client-rds under the Apache License 2.0
+@aws-sdk/client-ssm under the Apache License 2.0
+@aws-solutions-constructs/aws-lambda-dynamodb under the Apache License 2.0
+adm-zip under the MIT License
+aws-cdk-lib under the Apache License 2.0
+cdk-nag under the Apache License 2.0
+constructs under the Apache License 2.0
+projen under the Apache License 2.0
+source-map-support under the MIT License
+
+attrs under the MIT License
+aws-lambda-powertools under the MIT License
+boto3 under the Apache License 2.0
+botocore under the Apache License 2.0
+certifi under the Mozilla Public License 2.0
+charset-normalizer under the MIT License
+filelock under the The Unlicense
+idna under the BSD 3-Clause "New" or "Revised" License
+iniconfig under the MIT License
+jmespath under the MIT License
+pluggy under the MIT License
+pytest under the MIT License
+python-dateutil under the Apache License 2.0 and the BSD 3-Clause "New" or "Revised" License
+pytz under the MIT License
+requests under the Apache License 2.0
+rsa under the Apache License 2.0
+s3transfer under the Apache License 2.0
+six under the MIT License
+typing_extensions under the Python Software Foundation License 2.0
+urllib3 under the MIT License
diff --git a/README.md b/README.md
old mode 100755
new mode 100644
index 1e11f7d8..74ac2675
--- a/README.md
+++ b/README.md
@@ -1,236 +1,285 @@
-# Instance Scheduler on AWS (ID SO0030)
+# Instance Scheduler on AWS
-Instance Scheduler on AWS automates the starting and stopping of Amazon Elastic Compute Cloud (Amazon EC2) and Amazon Relational Database Service (Amazon RDS) instances.
+The Instance Scheduler on AWS solution automates the starting and stopping of Amazon Elastic Compute Cloud (Amazon EC2)
+and Amazon Relational Database Service (Amazon RDS) instances.
-This solution helps reduce operational costs by stopping resources that are not in use and starting them when they are needed. The cost savings can be significant if you leave all of your instances running at full utilization continuously.
+This solution helps reduce operational costs by stopping resources that are not in use and starting them when they are
+needed. The cost savings can be significant if you leave all of your instances running at full utilization continuously.
## Getting Started
-To understand how to use Instance Scheduler on AWS, please review the [implementation guide](https://docs.aws.amazon.com/solutions/latest/instance-scheduler-on-aws/solution-overview.html)
-on the [solution landing page](https://aws.amazon.com/solutions/implementations/instance-scheduler-on-aws/).
-To deploy the solution, see [Deploying the Solution](#deploying-the-solution)
-
+To understand how to use Instance Scheduler on AWS, please review the [implementation
+guide](https://docs.aws.amazon.com/solutions/latest/instance-scheduler-on-aws/solution-overview.html) on the [solution
+landing page](https://aws.amazon.com/solutions/implementations/instance-scheduler-on-aws/). To deploy the solution, see
+[Deploying the Solution](#deploying-the-solution).
## Repository Organization
```
-|- deployment/ - contains build scripts, deployment templates, and dist folders for staging assets.
- |- build-s3-dist.sh - builds the solution and copies artifacts to the appropriate /global-s3-assets or /regional-s3-assets folders.
- |- run-unit-tests.sh - runs the unit tests for the lambda files.
-|- source/ - all source code, scripts, tests, etc.
- |- app/ - lambda source file
- |- cli/ - scheduler-cli source files
- |- infrastructure/ - cdk source files
- |- pipeline - automated testing pipeline source files
+|- .github/ - GitHub issue and pull request templates
+|- .projen/ - projen-generated project metadata
+|- deployment/ - build scripts
+|- projenrc/ - projen source code
+|- source/ - project source code
+ |- app/ - AWS Lambda Function source code
+ |- cli/ - Instance Scheduler CLI source code
+ |- instance-scheduler/ - CDK source code
+ |- pipeline/ - automated testing pipeline source code
```
## Deploying the Solution
-***
+
### One-Click Deploy From Amazon Web Services
-Refer to the [solution landing page](https://aws.amazon.com/solutions/implementations/instance-scheduler-on-aws/)
-to deploy Instance Scheduler on AWS using our pre-packaged deployment assets.
-### Deploy from GitHub (CDK Deploy)
+Refer to the [solution landing page](https://aws.amazon.com/solutions/implementations/instance-scheduler-on-aws/) to
+deploy Instance Scheduler on AWS using our pre-packaged deployment assets.
+
+### Deploy from source code using CDK
+
+Instance Scheduler can be deployed to your AWS account directly from the source code using AWS Cloud Development Kit
+(CDK).
-Instance Scheduler can be deployed to your AWS account directly from the source code using `cdk deploy`.
+#### Prerequisites
+
+- cloned repository
+- AWS CLI v2
+- Node.JS 18
+- docker
+
+#### Deploying the hub stack
-#### Deploying the Primary Control Stack
```
-cd source/infrastructure
npm install
-cd instance-scheduler
-cdk bootstrap
-cdk deploy aws-instance-scheduler
+npx cdk bootstrap
+npx cdk deploy instance-scheduler-on-aws
```
-This will deploy the solution into your aws account using all default configuration settings.
-You will then need to update those settings to their desired values from the CloudFormation console
-by selecting the deployed template and clicking "Update" -> "Use Current Template".
+This will deploy the solution into your aws account using all default configuration settings. You will then need to
+update those settings to their desired values from the CloudFormation console by selecting the deployed template and
+clicking "Update" -> "Use Current Template".
-Refer to the [Implementation Guide](https://docs.aws.amazon.com/solutions/latest/instance-scheduler-on-aws/deployment.html#step1)
-for guidance on what each of the configuration parameters is for.
+Refer to the [Implementation
+Guide](https://docs.aws.amazon.com/solutions/latest/instance-scheduler-on-aws/deployment.html#step1) for guidance on
+what each of the configuration parameters is for.
#### Deploying Remote Stacks in Other Accounts
-To deploy the remote stack for cross-account scheduling, you will first need to have deployed the primary
-control stack. Then update your aws credentials to match those of the remote account you would like to schedule
-and deploy the remote stack.
-```
-/source/infrastructure/aws-instance-scheduler
-cdk bootstrap
-cdk deploy aws-instance-scheduler-remote --parameters InstanceSchedulerAccount={account-id} --parameters namespace={namespace} --parameters UsingAWSOrganizations={useOrgs}
+To deploy the remote stack for cross-account scheduling, you will first need to have deployed the primary control stack.
+Then update your aws credentials to match those of the remote account you would like to schedule and deploy the remote
+stack.
+
+```
+npx cdk bootstrap
+npx cdk deploy instance-scheduler-on-aws-remote --parameters InstanceSchedulerAccount={account-id} --parameters namespace={namespace} --parameters UsingAWSOrganizations={useOrgs}
```
+
Replace:
+
- {account-id} with the id of the account that contains the primary control stack.
- {namespace} with the same unique namespace that was provided to the primary control stack
-- {useOrgs} with the same value set in the primary control stack (yes/no)
+- {useOrgs} with the same value set in the primary control stack (Yes/No)
For example: `InstanceSchedulerAccount=111222333444`
-
### Deploy from GitHub (AWS Console)
-This method mimics the procedure used by AWS One-Click Deploy allowing you to deploy the solution
-from the AWS console using assets that you can control and update.
+
+This method mimics the procedure used by AWS One-Click Deploy allowing you to deploy the solution from the AWS console
+using assets that you can control and update.
#### Overview
-AWS Solutions use two buckets: a bucket for global access to templates, which is accessed via HTTPS, and regional buckets for access to assets within the region, such as Lambda code. You will need:
-* One global bucket that is accessed via the https end point. AWS CloudFormation templates are stored here. Ex. "mybucket"
-* One regional bucket for each region where you plan to deploy using the name of the global bucket as the root, and suffixed with the region name. Ex. "mybucket-us-east-1"
-* Your buckets should be encrypted and disallow public access.
+AWS Solutions use two buckets: a bucket for global access to templates, which is accessed via HTTPS, and regional
+buckets for access to assets within the region, such as Lambda code. You will need:
+
+- One global bucket that is accessed via the https end point. AWS CloudFormation templates are stored here. Ex.
+ "mybucket"
+- One regional bucket for each region where you plan to deploy using the name of the global bucket as the root, and
+ suffixed with the region name. Ex. "mybucket-us-east-1"
+- Your buckets should be encrypted and disallow public access.
#### You will need:
-* A Linux-compatible client with the AWS CLI v2, an accessible Docker daemon, and the latest versions of Python and NPM.
-* A clone (or fork) of this repo.
-* Two S3 buckets (minimum): 1 global and 1 for each region where you will deploy.
+- cloned repository
+- AWS CLI v2
+- Node.js 18
+- docker
+- Two S3 buckets (minimum): 1 global and 1 for each region where you will deploy.
#### Step 1 - Download from GitHub
-Clone the repository to a local directory on your linux client. Note: If you intend to
-modify Instance Scheduler you may wish to create your own fork of the GitHub repo and work from that.
-This allows you to check in any changes you make to your private copy of the solution.
+Clone the repository to a local directory on your linux client. Note: If you intend to modify Instance Scheduler you may
+wish to create your own fork of the GitHub repo and work from that. This allows you to check in any changes you make to
+your private copy of the solution.
#### Step 2 - Build the solution
-From the *deployment* folder in your cloned repo, run build-s3-dist.sh, passing the root name of
-your bucket(ex. mybucket), name of the solution (i.e. aws-instance-scheduler)
-and the version you are building (ex. v1.5.0).
-We recommend using a similar version based on the version downloaded from GitHub
-(ex. GitHub: v1.5.0, your build: v1.5.0.mybuild).
+From the _deployment_ folder in your cloned repo, run build-s3-dist.sh, passing the root name of your bucket(ex.
+mybucket), name of the solution (i.e. instance-scheduler-on-aws) and the version you are building (ex. v1.5.0). We
+recommend using a similar version based on the version downloaded from GitHub (ex. GitHub: v1.5.0, your build:
+v1.5.0.mybuild).
```
cd deployment
-chmod +x build-s3-dist.sh
-build-s3-dist.sh aws-instance-scheduler
+./build-s3-dist.sh instance-scheduler-on-aws
```
#### Step 3 - Upload to your buckets
The previous step will have generated several folders in your local directory including:
-```angular2html
+
+```
deployment/global-s3-assets
deployment/regional-s3-assets
```
-Upload the contents of `deployment/global-s3-assets` to your global bucket and `deployment/regional-s3-assets`
-to your regional buckets following the pattern
-`s3://///`.
+Upload the contents of `deployment/global-s3-assets` to your global bucket and `deployment/regional-s3-assets` to your
+regional buckets following the pattern `s3://///`.
For example:
+
```
//global assets
-s3://mybucket/aws-instance-scheduler/v1.5.0/instance-scheduler.template
-s3://mybucket/aws-instance-scheduler/v1.5.0/instance-scheduler-remote.template
+s3://mybucket/instance-scheduler-on-aws/v1.5.0/instance-scheduler.template
+s3://mybucket/instance-scheduler-on-aws/v1.5.0/instance-scheduler-remote.template
//regional assets
-s3://mybucket-us-east-1/aws-instance-scheduler/v1.5.0/f779f5b7643ba70e9a5e25c8898f4e4e8e54ca15b150eee1dd25c2c636b188b8.zip
-s3://mybucket-us-west-1/aws-instance-scheduler/v1.5.0/f779f5b7643ba70e9a5e25c8898f4e4e8e54ca15b150eee1dd25c2c636b188b8.zip
+s3://mybucket-us-east-1/instance-scheduler-on-aws/v1.5.0/f779f5b7643ba70e9a5e25c8898f4e4e8e54ca15b150eee1dd25c2c636b188b8.zip
+s3://mybucket-us-west-1/instance-scheduler-on-aws/v1.5.0/f779f5b7643ba70e9a5e25c8898f4e4e8e54ca15b150eee1dd25c2c636b188b8.zip
```
-*Note: The scheduler-cli is optional and does not need to be published to the global bucket for deploy to work.*
-
-
+_Note: The scheduler-cli is optional and does not need to be published to the global bucket for deploy to work._
#### Step 4 - Deploy The Solution
-Refer to the [Implementation Guide](https://docs.aws.amazon.com/solutions/latest/instance-scheduler-on-aws/deployment.html)
-for deployment instructions, using the link to the instance-scheduler.template from your bucket,
-rather than the one for AWS Solutions.
-Ex. https://mybucket.s3.amazonaws.com/aws-instance-scheduler/v1.5.0.mybuild/instance-scheduler.template
-
+Refer to the [Implementation
+Guide](https://docs.aws.amazon.com/solutions/latest/instance-scheduler-on-aws/deployment.html) for deployment
+instructions, using the link to the instance-scheduler.template from your bucket, rather than the one for AWS Solutions.
+Ex. https://mybucket.s3.amazonaws.com/instance-scheduler-on-aws/v1.5.0.mybuild/instance-scheduler.template
## Testing the Solution
-***
+
+### Prerequisites
+
+- cloned repository
+- AWS CLI v2
+- Node.js 18
+- docker
+- Python 3.10
+- tox
### Running Tests Locally
-To test the solution you will need to install tox:
```
-pip install tox
+npm install
+npm run test
```
-Then from the root directory of the solution,
-```
-//run all unit tests
-tox
+### Automated Testing Pipeline
-//test just the lambda code
-tox -e lambda
+Instance Scheduler on AWS includes an optional automated testing pipeline that can be deployed to automatically test any
+changes you develop for the solution on your own development fork. Once setup, this pipeline will automatically
+download, build, and test any changes that you push to a specified branch on your development fork.
-//test just the cdk code
-tox -e cdk
+The pipeline can be configured to automatically watch and pull from repos hosted on either [AWS
+CodeCommit](https://aws.amazon.com/codecommit/) or GitHub.
-//test just the cli code
-tox -e cli
-```
+#### Prerequisites
-### Automated Testing Pipeline
+- AWS account
+- repository fork
+- AWS CLI v2
+- Node.js 18
+- docker
+
+#### Step 0 (If Using GitHub) - Connect CodeStar to Your GitHub Account
-#### _Prerequisites - You must have an AWS account and a fork of this repo_
+For the pipeline to be able to test your changes, you must provide permission to access your development repo.
-Instance Scheduler on AWS includes an optional automated testing pipeline that can be deployed to automatically test any changes you
-develop for the solution on your own development fork. Once setup, this pipeline will automatically download,
-build, and test any changes that you push to a specified branch on your development fork.
+https://docs.aws.amazon.com/dtconsole/latest/userguide/connections-create-github.html
+_Note: CodeStar only needs access to your Instance Scheduler development fork, it does not need access to all
+repositories._
+Once the connection has been set up, make sure you save the connection ARN for the next step.
-#### Step 1 - Connect CodeStar to Your GitHub Account
+#### Step 1 - Prepare Your Environment
-For the pipeline to be able to test your changes, you must provide permission for CodeStar to
-access your development repo.
+In your local environment, first install all necessary dependencies and bootstrap your account for CDK deployment.
-https://docs.aws.amazon.com/dtconsole/latest/userguide/connections-create-github.html
+```
+npm install
+npx cdk bootstrap
+```
-_Note: CodeStar only needs access to your Instance Scheduler development fork, it does not need access to all repositories._
+#### Step 2 - Deploy the testing pipeline bootstrap stack
-Once the connection has been set up, make sure you save the connection ARN for the next step.
+```
+npx cdk deploy instance-scheduler-on-aws-testing-pipeline-bootstrap
+```
-#### Step 2 - Setup Pipeline Parameters
-Go to [Systems Manager Parameter Store](https://us-east-1.console.aws.amazon.com/systems-manager/parameters)
-and configure the following string parameters:
+Once the stack is deployed, Go to CloudFormation and [update the bootstrap
+stack](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-direct.html) with the
+configuration your pipeline should use
-- /InstanceScheduler-build/connection/arn -- the CodeStar connection ARN from the previous step
-- /InstanceScheduler-build/connection/owner -- the GitHub owner of your fork
-- /InstanceScheduler-build/connection/repo -- the repo name of your fork
-- /InstanceScheduler-build/connection/branch -- The branch in your fork that you want to test
+At a minimum you must provide:
+
+- repoName -- the name of your forked repo (either in CodeCommit or GitHub)
+- repoBranch -- The branch in your fork that should be watched and pulled from for testing
+
+if sourcing from GitHub instead of CodeCommit, you must also provide:
+
+- codestarArn -- the CodeStar connection ARN from the previous step
+- repoArn -- the GitHub owner of your fork
+
+For example, if your GitHub username is "myUser" and you would like to test changes pushed to the develop branch of your
+fork the values you would need to set would be:
-For example, if your GitHub username is "myUser" and you would like to test changes pushed to the develop branch of your fork
-the values you would need to set would be:
```
-arn = {arn from Step 1}
+arn = {arn from Step 0}
owner = myUser
-repo = aws-instance-scheduler
+repo = instance-scheduler-on-aws
branch = develop
```
#### Step 3 - Deploy the Testing Pipeline
```
-cd source/infrastructure
-npm install
-cd pipeline
-cdk bootstrap
-cdk deploy aws-instance-scheduler-testing-pipeline
+# source from CodeCommit
+npx cdk deploy instance-scheduler-on-aws-testing-pipeline --context instance-scheduler-on-aws-pipeline-source=codecommit
+
+# source from GitHub
+npx cdk deploy instance-scheduler-on-aws-testing-pipeline --context instance-scheduler-on-aws-pipeline-source=codestar
```
+
+_note: If you do not provide a context, the pipeline will default to using codecommit._
+
This will deploy the automated testing pipeline into your AWS account which will then begin running tests against your
development fork automatically.
To view the results. Go to [CodePipeline](https://us-east-1.console.aws.amazon.com/codesuite/codepipeline/pipelines) and
-click on the pipeline that begins with aws-instance-scheduler-testing-pipeline.
+click on the pipeline that begins with instance-scheduler-on-aws-testing-pipeline.
-## CDK Documentation
+## Modifying the solution
-AWS Instance Scheduler templates are generated using AWS CDK, for further information on CDK
-please refer to the [documentation](https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html).
+### projen
+
+This solution uses [projen](https://projen.io/) to manage certain project files. If you need to modify any of these
+files, modify the source in [.projenrc.ts](./.projenrc.ts) and run `projen` to regenerate the files.
+
+## CDK Documentation
+Instance Scheduler on AWS templates are generated using AWS CDK, for further information on CDK please refer to the
+[documentation](https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html).
-***
+---
Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
-Licensed under the Apache License Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at
+Licensed under the Apache License Version 2.0 (the "License"). You may not use this file except in compliance with the
+License. A copy of the License is located at
http://www.apache.org/licenses/
-or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions and limitations under the License.
+or in the "[LICENSE](./LICENSE)" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing
+permissions and limitations under the License.
diff --git a/buildspec.yml b/buildspec.yml
old mode 100755
new mode 100644
index a436e7c0..b1b3fee7
--- a/buildspec.yml
+++ b/buildspec.yml
@@ -1,37 +1,35 @@
version: 0.2
-
phases:
install:
runtime-versions:
- python: 3.10
+ nodejs: 18
+ python: 3.11
commands:
- - pip install --upgrade pip
+ - npm install --location=global npm@latest
+ - pyenv install -s 3.8 3.9
+ - pyenv global $PYTHON_311_VERSION 3.9 3.8
+ - python -m pip install -U pip setuptools poetry tox
+ - npm ci
pre_build:
commands:
- - echo "Installing dependencies and executing unit tests - `pwd`"
- - cd deployment
- - chmod +x ./run-unit-tests.sh && ./run-unit-tests.sh
- - echo "Installing dependencies and executing unit tests completed `date`"
+ - cd ./deployment
+ - ./build-open-source-dist.sh
+ - cd ..
+ - npm run test:ci
build:
commands:
- - echo "`pwd`"
- - echo "Starting build `date` in `pwd`"
- - chmod +x ./build-s3-dist.sh && ./build-s3-dist.sh $DIST_OUTPUT_BUCKET $SOLUTION_NAME $VERSION
- - echo "Build completed `date`"
-
+ - cd ./deployment
+ - ./build-s3-dist.sh $DIST_OUTPUT_BUCKET $SOLUTION_NAME $VERSION
+ - cd ..
post_build:
commands:
- - echo "Retrieving next stage buildspec `date` in `pwd`"
- - aws s3 cp s3://solutions-build-assets/changelog-spec.yml ../buildspec.yml
- - echo "Retrieving next stage buildspec complete"
- - echo "Post build completed on `date`"
- - mkdir -p open-source
- - touch open-source/source-is-on-github
-
+ - rm ./deployment/global-s3-assets/instance-scheduler-on-aws-testing-pipeline.template
+ - rm ./deployment/global-s3-assets/instance-scheduler-on-aws-testing-pipeline-*.template
+ - rm ./deployment/global-s3-assets/instance-scheduler-on-aws-end-to-end-testing-*.template
artifacts:
files:
- - deployment/**/*
- - source/**/*
- - buildspec.yml
- - CHANGELOG.md
- - sonar-project.properties
+ - '**/*'
+ exclude-paths:
+ - '**/.mypy_cache/**/*'
+ - '**/__pycache__/**'
+ - '**/.tox/**/*'
diff --git a/cdk.json b/cdk.json
new file mode 100644
index 00000000..a1a051e7
--- /dev/null
+++ b/cdk.json
@@ -0,0 +1,29 @@
+{
+ "app": "npx ts-node -P tsconfig.json --prefer-ts-exts source/instance-scheduler.ts",
+ "context": {
+ "solutionId": "SO0030",
+ "solutionName": "instance-scheduler-on-aws",
+ "appRegApplicationName": "AWS-Solutions",
+ "appRegSolutionName": "instance-scheduler-on-aws",
+ "instance-scheduler-on-aws-pipeline-source": "codecommit"
+ },
+ "output": "build/cdk.out",
+ "build": "npx projen bundle",
+ "watch": {
+ "include": [
+ "source/**/*.ts",
+ "source/instance-scheduler/tests/**/*.ts"
+ ],
+ "exclude": [
+ "README.md",
+ "cdk*.json",
+ "**/*.d.ts",
+ "**/*.js",
+ "tsconfig.json",
+ "package*.json",
+ "yarn.lock",
+ "node_modules"
+ ]
+ },
+ "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"."
+}
diff --git a/deployment/build-open-source-dist.sh b/deployment/build-open-source-dist.sh
new file mode 100755
index 00000000..4926b27d
--- /dev/null
+++ b/deployment/build-open-source-dist.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+#
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+#
+
+#
+# This assumes all of the OS-level configuration has been completed and git repo has already been cloned
+#
+# This script should be run from the repo's deployment directory
+
+#"$DEBUG" == 'true' -> enable detailed messages.
+#set -x enables a mode of the shell where all executed commands are printed to the terminal
+[[ $DEBUG ]] && set -x
+set -eou pipefail
+
+solution_name="instance-scheduler-on-aws"
+
+# Get reference for all important folders
+project_root="$PWD/.."
+deployment_dir="$PWD"
+open_source_dist_dir="$deployment_dir/open-source"
+
+echo "------------------------------------------------------------------------------"
+echo "[Init] Remove any old dist files from previous runs"
+echo "------------------------------------------------------------------------------"
+
+rm -rf $open_source_dist_dir
+mkdir -p $open_source_dist_dir
+
+echo "------------------------------------------------------------------------------"
+echo "Create zip"
+echo "------------------------------------------------------------------------------"
+
+cd $project_root
+
+zip -q -r9 "$open_source_dist_dir"/"$solution_name" . \
+ -x ".git/*" \
+ -x "*/.idea/*" \
+ -x "*/.mypy_cache/*" \
+ -x "*/.pytest_cache/*" \
+ -x "*/__pycache__/*" \
+ -x "*/.tox/*" \
+ -x "*/.coverage" \
+ -x "coverage/*" \
+ -x ".venv/*" \
+ -x "*/.venv/*" \
+ -x "build/*" \
+ -x "deployment/global-s3-assets/*" \
+ -x "deployment/open-source/*" \
+ -x "deployment/regional-s3-assets/*" \
+ -x "deployment/test-reports/*" \
+ -x "deployment/coverage-reports/*" \
+ -x "node_modules/*" \
+ -x "*/node_modules/*" \
+ -x "*/dist/*" \
+ -x "*/cdk.out/*" \
+ -x ".viperlightrc.*" \
+ -x "codescan-*.sh"
+
+cd $deployment_dir
+echo "Completed building $solution_name.zip dist"
diff --git a/deployment/build-s3-dist.sh b/deployment/build-s3-dist.sh
index 4f29a017..7ea7ab15 100755
--- a/deployment/build-s3-dist.sh
+++ b/deployment/build-s3-dist.sh
@@ -1,102 +1,84 @@
-#!/bin/bash
-#
-# Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
-# with the License. A copy of the License is located at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES
-# OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
-# and limitations under the License.
-#
-
-
-# Check to see if the required parameters have been provided:
-if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then
+#!/usr/bin/env bash
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+[[ $DEBUG ]] && set -x
+set -eu -o pipefail
+
+header() {
+ declare text=$1
+ echo "------------------------------------------------------------------------------"
+ echo "$text"
+ echo "------------------------------------------------------------------------------"
+}
+
+usage() {
echo "Please provide the base source bucket name, trademark approved solution name and version where the lambda code will eventually reside."
echo "For example: ./build-s3-dist.sh solutions trademarked-solution-name v1.0.0"
- exit 1
-fi
-
-#"$DEBUG" == 'true' -> enable detailed messages.
-#set -x enables a mode of the shell where all executed commands are printed to the terminal
-[[ $DEBUG ]] && set -x
-set -eou pipefail
-
-export DIST_OUTPUT_BUCKET=$1
-export SOLUTION_NAME=$2
-export DIST_VERSION=$3
-
-# Get reference for all important folders
-project_root="$PWD/.."
-deployment_dir="$PWD"
-#output folders
-global_dist_dir="$deployment_dir/global-s3-assets"
-regional_dist_dir="$deployment_dir/regional-s3-assets"
-
-#build directories
-build_dir="$project_root/build"
-cdk_out_dir="$build_dir/cdk.out"
-
-#project folders
-lambda_source_dir="$project_root/source/app" #not currently needed, but here for reference
-cli_source_dir="$project_root/source/cli"
-cdk_source_dir="$project_root/source/infrastructure/instance-scheduler"
-
-
-echo "------------------------------------------------------------------------------"
-echo "[Init] Remove any old dist files from previous runs"
-echo "------------------------------------------------------------------------------"
-
-rm -rf $global_dist_dir
-mkdir -p $global_dist_dir
-rm -rf $regional_dist_dir
-mkdir -p $regional_dist_dir
-rm -rf $build_dir
-mkdir -p $build_dir
-rm -rf $cdk_out_dir
-
-
-echo "------------------------------------------------------------------------------"
-echo "[Synth] CDK Project"
-echo "------------------------------------------------------------------------------"
-
-# Install the npm install in the source folder
-cd "$cdk_source_dir"
-npm ci
-npm run synth -- --no-version-reporting
-
-echo "------------------------------------------------------------------------------"
-echo "[Packing] Template artifacts"
-echo "------------------------------------------------------------------------------"
-
-# copy templates to global_dist_dir
-echo "Move templates from staging to global_dist_dir"
-cp "$cdk_out_dir"/*.template.json "$global_dist_dir"/
-
-
-# Rename all *.template.json files to *.template
-echo "Rename all *.template.json to *.template"
-echo "copy templates and rename"
-for f in $global_dist_dir/*.template.json; do
- mv -- "$f" "${f%.template.json}.template"
-done
-
-
-echo "------------------------------------------------------------------------------"
-echo "[CDK-Helper] Copy the Lambda Asset"
-echo "------------------------------------------------------------------------------"
-cd "$deployment_dir"/cdk-solution-helper/asset-packager && npm ci
-npx ts-node ./index "$cdk_out_dir" "$regional_dist_dir"
-
-echo "------------------------------------------------------------------------------"
-echo "[Scheduler-CLI] Package the Scheduler cli"
-echo "------------------------------------------------------------------------------"
-cp -pr $cli_source_dir $build_dir/
-cd "$build_dir/cli"
-echo "Build the scheduler cli package"
-zip -q --recurse-paths ./scheduler-cli.zip instance_scheduler_cli/* poetry.lock pyproject.toml instance-scheduler-cli-runner.py
-echo "Copy the scheduler cli package to $global_dist_dir"
-cp -pr ./scheduler-cli.zip $global_dist_dir/
+}
+
+main() {
+ declare DIST_OUTPUT_BUCKET=$1 SOLUTION_NAME=$2 VERSION=$3
+ # Check to see if the required parameters have been provided:
+ if [ -z "$DIST_OUTPUT_BUCKET" ] || [ -z "$SOLUTION_NAME" ] || [ -z "$VERSION" ]; then
+ usage
+ exit 1
+ fi
+
+ export DIST_OUTPUT_BUCKET
+ export SOLUTION_NAME
+ export VERSION
+
+ # Get reference for all important folders
+ local project_root=$(dirname "$(cd -P -- "$(dirname "$0")" && pwd -P)")
+ local deployment_dir="$project_root"/deployment
+ #output folders
+ local global_dist_dir="$deployment_dir"/global-s3-assets
+ local regional_dist_dir="$deployment_dir"/regional-s3-assets
+
+ #build directories
+ local build_dir="$project_root"/build
+ local cdk_out_dir="$build_dir"/cdk.out
+
+ #project folders
+ local cli_source_dir="$project_root/source/cli"
+
+ header "[Init] Remove any old dist files from previous runs"
+
+ rm -rf "$global_dist_dir"
+ mkdir -p "$global_dist_dir"
+ rm -rf "$regional_dist_dir"
+ mkdir -p "$regional_dist_dir"
+ rm -rf "$build_dir"
+ mkdir -p "$build_dir"
+
+ header "[Synth] CDK Project"
+
+ npm run synth -- --no-version-reporting
+
+ header "[Packing] Template artifacts"
+
+ # copy templates to global_dist_dir
+ echo "Move templates from staging to global_dist_dir"
+ cp "$cdk_out_dir"/*.template.json "$global_dist_dir"/
+
+ # Rename all *.template.json files to *.template
+ echo "Rename all *.template.json to *.template"
+ echo "copy templates and rename"
+ for f in "$global_dist_dir"/*.template.json; do
+ mv -- "$f" "${f%.template.json}.template"
+ done
+
+ header "[CDK-Helper] Copy the Lambda Asset"
+ pushd "$deployment_dir"/cdk-solution-helper/asset-packager
+ npm ci
+ npx ts-node ./index "$cdk_out_dir" "$regional_dist_dir"
+ popd
+
+ header "[Scheduler-CLI] Package the Scheduler cli"
+ pushd "$cli_source_dir"
+ python -m poetry build
+ cp ./dist/* "$global_dist_dir"
+ popd
+}
+
+main "$@"
diff --git a/deployment/cdk-solution-helper/asset-packager/__tests__/asset-packager.test.ts b/deployment/cdk-solution-helper/asset-packager/__tests__/asset-packager.test.ts
index 28cbdc7c..1fffe85c 100644
--- a/deployment/cdk-solution-helper/asset-packager/__tests__/asset-packager.test.ts
+++ b/deployment/cdk-solution-helper/asset-packager/__tests__/asset-packager.test.ts
@@ -1,7 +1,5 @@
-/*
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
const readdirMock = jest.fn();
const addLocalFolderMock = jest.fn();
@@ -114,7 +112,7 @@ describe("CDKAssetPackager", () => {
await assetPackager.moveZips(__outputPath);
expect(renameMock).toBeCalledWith(
path.join(__assetPath, __asset2),
- path.join(__outputPath, __asset2.split("asset.").pop()!)
+ path.join(__outputPath, __asset2.split("asset.").pop() ?? "unexpected"),
);
});
diff --git a/deployment/cdk-solution-helper/asset-packager/__tests__/handler.test.ts b/deployment/cdk-solution-helper/asset-packager/__tests__/handler.test.ts
index d474ac9c..be2c5668 100644
--- a/deployment/cdk-solution-helper/asset-packager/__tests__/handler.test.ts
+++ b/deployment/cdk-solution-helper/asset-packager/__tests__/handler.test.ts
@@ -1,7 +1,5 @@
-/*
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
import path from "path";
import { existsSync } from "fs";
@@ -49,7 +47,7 @@ describe("Handler", () => {
const mockAssetPath = path.join(__assetDirectoryPath, zipName);
await writeFile(mockAssetPath, "NoOp");
await expect(handler(__assetDirectoryPath, __outputPath)).resolves.toBeUndefined();
- expect(existsSync(path.join(__outputPath, zipName.split("asset.").pop()!))).toBe(true);
+ expect(existsSync(path.join(__outputPath, zipName.split("asset.").pop() ?? "unexpected"))).toBe(true);
});
afterAll(async function Cleanup() {
diff --git a/deployment/cdk-solution-helper/asset-packager/asset-packager.ts b/deployment/cdk-solution-helper/asset-packager/asset-packager.ts
index e66be2fb..1f31e638 100644
--- a/deployment/cdk-solution-helper/asset-packager/asset-packager.ts
+++ b/deployment/cdk-solution-helper/asset-packager/asset-packager.ts
@@ -1,7 +1,5 @@
-/*
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
import { readdir, lstat, rename } from "node:fs/promises";
import path from "path";
@@ -53,7 +51,11 @@ export class CDKAssetPackager {
const allFiles = await readdir(this.assetFolderPath);
const allZipPaths = allFiles.filter((file) => path.extname(file) === ".zip");
for (const zipPath of allZipPaths) {
- await rename(path.join(this.assetFolderPath, zipPath), path.join(outputPath, zipPath.split("asset.").pop()!));
+ const hashPart = zipPath.split("asset.").pop();
+ if (!hashPart) {
+ throw new Error(`Unexpected path: {${zipPath}}`);
+ }
+ await rename(path.join(this.assetFolderPath, zipPath), path.join(outputPath, hashPart));
// remove cdk prepended string "asset.*"
}
}
diff --git a/deployment/cdk-solution-helper/asset-packager/index.ts b/deployment/cdk-solution-helper/asset-packager/index.ts
index 18e572f5..baf96a77 100644
--- a/deployment/cdk-solution-helper/asset-packager/index.ts
+++ b/deployment/cdk-solution-helper/asset-packager/index.ts
@@ -1,10 +1,6 @@
-/*
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
import { CDKAssetPackager } from "./asset-packager";
-import path from "path";
export async function handler(cdkAssetFolderPath: string | undefined, outputPath: string | undefined) {
if (!cdkAssetFolderPath || !outputPath) throw new Error("undefined input path");
diff --git a/deployment/cdk-solution-helper/jest.config.ts b/deployment/cdk-solution-helper/jest.config.ts
index 0a8d8ffc..0dae36ec 100644
--- a/deployment/cdk-solution-helper/jest.config.ts
+++ b/deployment/cdk-solution-helper/jest.config.ts
@@ -1,8 +1,5 @@
-/*
- * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
import type { Config } from "jest";
const config: Config = {
diff --git a/deployment/cdk-solution-helper/package-lock.json b/deployment/cdk-solution-helper/package-lock.json
index 6d4f8c35..d9abdd12 100644
--- a/deployment/cdk-solution-helper/package-lock.json
+++ b/deployment/cdk-solution-helper/package-lock.json
@@ -1,7 +1,7 @@
{
"name": "cdk-solution-helper",
"version": "1.0.0",
- "lockfileVersion": 2,
+ "lockfileVersion": 3,
"requires": true,
"packages": {
"": {
@@ -10,25 +10,25 @@
"license": "Apache-2.0",
"dependencies": {
"adm-zip": "^0.5.10",
- "aws-cdk-lib": "^2.63.0"
+ "aws-cdk-lib": "^2.87.0"
},
"devDependencies": {
"@types/adm-zip": "^0.5.0",
- "@types/jest": "^29.4.0",
- "@types/node": "^18.11.18",
- "jest": "^29.4.1",
- "ts-jest": "^29.0.5",
+ "@types/jest": "^29.5.3",
+ "@types/node": "^18.16.19",
+ "jest": "^29.6.1",
+ "ts-jest": "^29.1.1",
"ts-node": "^10.9.1",
- "typescript": "^4.9.4"
+ "typescript": "^5.1.6"
}
},
"node_modules/@ampproject/remapping": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
- "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==",
+ "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.1.0",
+ "@jridgewell/gen-mapping": "^0.3.0",
"@jridgewell/trace-mapping": "^0.3.9"
},
"engines": {
@@ -36,62 +36,62 @@
}
},
"node_modules/@aws-cdk/asset-awscli-v1": {
- "version": "2.2.52",
- "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.52.tgz",
- "integrity": "sha512-9dBPrvByWrUOcs5Rjwv08FWSummo1Uk/EgE3dCFDqvIqlSTudEmu6TGU3zrs00rfcAjqDv6gBuSttzG5f9tfdQ=="
+ "version": "2.2.200",
+ "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.200.tgz",
+ "integrity": "sha512-Kf5J8DfJK4wZFWT2Myca0lhwke7LwHcHBo+4TvWOGJrFVVKVuuiLCkzPPRBQQVDj0Vtn2NBokZAz8pfMpAqAKg=="
},
"node_modules/@aws-cdk/asset-kubectl-v20": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@aws-cdk/asset-kubectl-v20/-/asset-kubectl-v20-2.1.1.tgz",
- "integrity": "sha512-U1ntiX8XiMRRRH5J1IdC+1t5CE89015cwyt5U63Cpk0GnMlN5+h9WsWMlKlPXZR4rdq/m806JRlBMRpBUB2Dhw=="
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@aws-cdk/asset-kubectl-v20/-/asset-kubectl-v20-2.1.2.tgz",
+ "integrity": "sha512-3M2tELJOxQv0apCIiuKQ4pAbncz9GuLwnKFqxifWfe77wuMxyTRPmxssYHs42ePqzap1LT6GDcPygGs+hHstLg=="
},
"node_modules/@aws-cdk/asset-node-proxy-agent-v5": {
- "version": "2.0.42",
- "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v5/-/asset-node-proxy-agent-v5-2.0.42.tgz",
- "integrity": "sha512-PxvP1UU2xa4k3Ea78DxAYY8ADvwWZ/nPu+xsjQLsT+MP+aB3RZ3pGc/fNlH7Rg56Zyb/j3GSdihAy4Oi5xa+TQ=="
+ "version": "2.0.165",
+ "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v5/-/asset-node-proxy-agent-v5-2.0.165.tgz",
+ "integrity": "sha512-bsyLQD/vqXQcc9RDmlM1XqiFNO/yewgVFXmkMcQkndJbmE/jgYkzewwYGrBlfL725hGLQipXq19+jwWwdsXQqg=="
},
"node_modules/@babel/code-frame": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
- "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz",
+ "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==",
"dev": true,
"dependencies": {
- "@babel/highlight": "^7.18.6"
+ "@babel/highlight": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/compat-data": {
- "version": "7.20.10",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.10.tgz",
- "integrity": "sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg==",
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz",
+ "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/core": {
- "version": "7.20.12",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz",
- "integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==",
- "dev": true,
- "dependencies": {
- "@ampproject/remapping": "^2.1.0",
- "@babel/code-frame": "^7.18.6",
- "@babel/generator": "^7.20.7",
- "@babel/helper-compilation-targets": "^7.20.7",
- "@babel/helper-module-transforms": "^7.20.11",
- "@babel/helpers": "^7.20.7",
- "@babel/parser": "^7.20.7",
- "@babel/template": "^7.20.7",
- "@babel/traverse": "^7.20.12",
- "@babel/types": "^7.20.7",
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz",
+ "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==",
+ "dev": true,
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.22.5",
+ "@babel/generator": "^7.22.9",
+ "@babel/helper-compilation-targets": "^7.22.9",
+ "@babel/helper-module-transforms": "^7.22.9",
+ "@babel/helpers": "^7.22.6",
+ "@babel/parser": "^7.22.7",
+ "@babel/template": "^7.22.5",
+ "@babel/traverse": "^7.22.8",
+ "@babel/types": "^7.22.5",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
"json5": "^2.2.2",
- "semver": "^6.3.0"
+ "semver": "^6.3.1"
},
"engines": {
"node": ">=6.9.0"
@@ -108,44 +108,31 @@
"dev": true
},
"node_modules/@babel/generator": {
- "version": "7.20.7",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.7.tgz",
- "integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==",
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.9.tgz",
+ "integrity": "sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==",
"dev": true,
"dependencies": {
- "@babel/types": "^7.20.7",
+ "@babel/types": "^7.22.5",
"@jridgewell/gen-mapping": "^0.3.2",
+ "@jridgewell/trace-mapping": "^0.3.17",
"jsesc": "^2.5.1"
},
"engines": {
"node": ">=6.9.0"
}
},
- "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
- "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
- "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/@babel/helper-compilation-targets": {
- "version": "7.20.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz",
- "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==",
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz",
+ "integrity": "sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==",
"dev": true,
"dependencies": {
- "@babel/compat-data": "^7.20.5",
- "@babel/helper-validator-option": "^7.18.6",
- "browserslist": "^4.21.3",
+ "@babel/compat-data": "^7.22.9",
+ "@babel/helper-validator-option": "^7.22.5",
+ "browserslist": "^4.21.9",
"lru-cache": "^5.1.1",
- "semver": "^6.3.0"
+ "semver": "^6.3.1"
},
"engines": {
"node": ">=6.9.0"
@@ -155,151 +142,151 @@
}
},
"node_modules/@babel/helper-environment-visitor": {
- "version": "7.18.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz",
- "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
+ "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-function-name": {
- "version": "7.19.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz",
- "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
+ "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
"dev": true,
"dependencies": {
- "@babel/template": "^7.18.10",
- "@babel/types": "^7.19.0"
+ "@babel/template": "^7.22.5",
+ "@babel/types": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-hoist-variables": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz",
- "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==",
+ "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.18.6"
+ "@babel/types": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-imports": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz",
- "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz",
+ "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==",
"dev": true,
"dependencies": {
- "@babel/types": "^7.18.6"
+ "@babel/types": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-transforms": {
- "version": "7.20.11",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz",
- "integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-environment-visitor": "^7.18.9",
- "@babel/helper-module-imports": "^7.18.6",
- "@babel/helper-simple-access": "^7.20.2",
- "@babel/helper-split-export-declaration": "^7.18.6",
- "@babel/helper-validator-identifier": "^7.19.1",
- "@babel/template": "^7.20.7",
- "@babel/traverse": "^7.20.10",
- "@babel/types": "^7.20.7"
+ "version": "7.22.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz",
+ "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-module-imports": "^7.22.5",
+ "@babel/helper-simple-access": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "@babel/helper-validator-identifier": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
}
},
"node_modules/@babel/helper-plugin-utils": {
- "version": "7.20.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz",
- "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==",
+ "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.20.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz",
- "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==",
+ "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.20.2"
+ "@babel/types": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-split-export-declaration": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz",
- "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==",
+ "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.18.6"
+ "@babel/types": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-string-parser": {
- "version": "7.19.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz",
- "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==",
+ "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.19.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
- "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz",
+ "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-option": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz",
- "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz",
+ "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helpers": {
- "version": "7.20.13",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.13.tgz",
- "integrity": "sha512-nzJ0DWCL3gB5RCXbUO3KIMMsBY2Eqbx8mBpKGE/02PgyRQFcPQLbkQ1vyy596mZLaP+dAfD+R4ckASzNVmW3jg==",
+ "version": "7.22.6",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz",
+ "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==",
"dev": true,
"dependencies": {
- "@babel/template": "^7.20.7",
- "@babel/traverse": "^7.20.13",
- "@babel/types": "^7.20.7"
+ "@babel/template": "^7.22.5",
+ "@babel/traverse": "^7.22.6",
+ "@babel/types": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/highlight": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
- "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz",
+ "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==",
"dev": true,
"dependencies": {
- "@babel/helper-validator-identifier": "^7.18.6",
+ "@babel/helper-validator-identifier": "^7.22.5",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
},
@@ -379,9 +366,9 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.20.13",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.13.tgz",
- "integrity": "sha512-gFDLKMfpiXCsjt4za2JA9oTMn70CeseCehb11kRZgvd7+F67Hih3OHOK24cRrWECJ/ljfPGac6ygXAs/C8kIvw==",
+ "version": "7.22.7",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz",
+ "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==",
"dev": true,
"bin": {
"parser": "bin/babel-parser.js"
@@ -451,12 +438,12 @@
}
},
"node_modules/@babel/plugin-syntax-jsx": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz",
- "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==",
+ "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.18.6"
+ "@babel/helper-plugin-utils": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
@@ -553,12 +540,12 @@
}
},
"node_modules/@babel/plugin-syntax-typescript": {
- "version": "7.20.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz",
- "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==",
+ "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.19.0"
+ "@babel/helper-plugin-utils": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
@@ -568,33 +555,33 @@
}
},
"node_modules/@babel/template": {
- "version": "7.20.7",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz",
- "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz",
+ "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==",
"dev": true,
"dependencies": {
- "@babel/code-frame": "^7.18.6",
- "@babel/parser": "^7.20.7",
- "@babel/types": "^7.20.7"
+ "@babel/code-frame": "^7.22.5",
+ "@babel/parser": "^7.22.5",
+ "@babel/types": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
- "version": "7.20.13",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.13.tgz",
- "integrity": "sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ==",
- "dev": true,
- "dependencies": {
- "@babel/code-frame": "^7.18.6",
- "@babel/generator": "^7.20.7",
- "@babel/helper-environment-visitor": "^7.18.9",
- "@babel/helper-function-name": "^7.19.0",
- "@babel/helper-hoist-variables": "^7.18.6",
- "@babel/helper-split-export-declaration": "^7.18.6",
- "@babel/parser": "^7.20.13",
- "@babel/types": "^7.20.7",
+ "version": "7.22.8",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz",
+ "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.22.5",
+ "@babel/generator": "^7.22.7",
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-function-name": "^7.22.5",
+ "@babel/helper-hoist-variables": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "@babel/parser": "^7.22.7",
+ "@babel/types": "^7.22.5",
"debug": "^4.1.0",
"globals": "^11.1.0"
},
@@ -603,13 +590,13 @@
}
},
"node_modules/@babel/types": {
- "version": "7.20.7",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz",
- "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==",
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz",
+ "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==",
"dev": true,
"dependencies": {
- "@babel/helper-string-parser": "^7.19.4",
- "@babel/helper-validator-identifier": "^7.19.1",
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.5",
"to-fast-properties": "^2.0.0"
},
"engines": {
@@ -634,6 +621,16 @@
"node": ">=12"
}
},
+ "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
+ "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
"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",
@@ -660,16 +657,16 @@
}
},
"node_modules/@jest/console": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.4.1.tgz",
- "integrity": "sha512-m+XpwKSi3PPM9znm5NGS8bBReeAJJpSkL1OuFCqaMaJL2YX9YXLkkI+MBchMPwu+ZuM2rynL51sgfkQteQ1CKQ==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.1.tgz",
+ "integrity": "sha512-Aj772AYgwTSr5w8qnyoJ0eDYvN6bMsH3ORH1ivMotrInHLKdUz6BDlaEXHdM6kODaBIkNIyQGzsMvRdOv7VG7Q==",
"dev": true,
"dependencies": {
- "@jest/types": "^29.4.1",
+ "@jest/types": "^29.6.1",
"@types/node": "*",
"chalk": "^4.0.0",
- "jest-message-util": "^29.4.1",
- "jest-util": "^29.4.1",
+ "jest-message-util": "^29.6.1",
+ "jest-util": "^29.6.1",
"slash": "^3.0.0"
},
"engines": {
@@ -677,37 +674,37 @@
}
},
"node_modules/@jest/core": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.4.1.tgz",
- "integrity": "sha512-RXFTohpBqpaTebNdg5l3I5yadnKo9zLBajMT0I38D0tDhreVBYv3fA8kywthI00sWxPztWLD3yjiUkewwu/wKA==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.1.tgz",
+ "integrity": "sha512-CcowHypRSm5oYQ1obz1wfvkjZZ2qoQlrKKvlfPwh5jUXVU12TWr2qMeH8chLMuTFzHh5a1g2yaqlqDICbr+ukQ==",
"dev": true,
"dependencies": {
- "@jest/console": "^29.4.1",
- "@jest/reporters": "^29.4.1",
- "@jest/test-result": "^29.4.1",
- "@jest/transform": "^29.4.1",
- "@jest/types": "^29.4.1",
+ "@jest/console": "^29.6.1",
+ "@jest/reporters": "^29.6.1",
+ "@jest/test-result": "^29.6.1",
+ "@jest/transform": "^29.6.1",
+ "@jest/types": "^29.6.1",
"@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.4.0",
- "jest-config": "^29.4.1",
- "jest-haste-map": "^29.4.1",
- "jest-message-util": "^29.4.1",
- "jest-regex-util": "^29.2.0",
- "jest-resolve": "^29.4.1",
- "jest-resolve-dependencies": "^29.4.1",
- "jest-runner": "^29.4.1",
- "jest-runtime": "^29.4.1",
- "jest-snapshot": "^29.4.1",
- "jest-util": "^29.4.1",
- "jest-validate": "^29.4.1",
- "jest-watcher": "^29.4.1",
+ "jest-changed-files": "^29.5.0",
+ "jest-config": "^29.6.1",
+ "jest-haste-map": "^29.6.1",
+ "jest-message-util": "^29.6.1",
+ "jest-regex-util": "^29.4.3",
+ "jest-resolve": "^29.6.1",
+ "jest-resolve-dependencies": "^29.6.1",
+ "jest-runner": "^29.6.1",
+ "jest-runtime": "^29.6.1",
+ "jest-snapshot": "^29.6.1",
+ "jest-util": "^29.6.1",
+ "jest-validate": "^29.6.1",
+ "jest-watcher": "^29.6.1",
"micromatch": "^4.0.4",
- "pretty-format": "^29.4.1",
+ "pretty-format": "^29.6.1",
"slash": "^3.0.0",
"strip-ansi": "^6.0.0"
},
@@ -724,89 +721,89 @@
}
},
"node_modules/@jest/environment": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.4.1.tgz",
- "integrity": "sha512-pJ14dHGSQke7Q3mkL/UZR9ZtTOxqskZaC91NzamEH4dlKRt42W+maRBXiw/LWkdJe+P0f/zDR37+SPMplMRlPg==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.1.tgz",
+ "integrity": "sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A==",
"dev": true,
"dependencies": {
- "@jest/fake-timers": "^29.4.1",
- "@jest/types": "^29.4.1",
+ "@jest/fake-timers": "^29.6.1",
+ "@jest/types": "^29.6.1",
"@types/node": "*",
- "jest-mock": "^29.4.1"
+ "jest-mock": "^29.6.1"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/expect": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.4.1.tgz",
- "integrity": "sha512-ZxKJP5DTUNF2XkpJeZIzvnzF1KkfrhEF6Rz0HGG69fHl6Bgx5/GoU3XyaeFYEjuuKSOOsbqD/k72wFvFxc3iTw==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.1.tgz",
+ "integrity": "sha512-N5xlPrAYaRNyFgVf2s9Uyyvr795jnB6rObuPx4QFvNJz8aAjpZUDfO4bh5G/xuplMID8PrnuF1+SfSyDxhsgYg==",
"dev": true,
"dependencies": {
- "expect": "^29.4.1",
- "jest-snapshot": "^29.4.1"
+ "expect": "^29.6.1",
+ "jest-snapshot": "^29.6.1"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/expect-utils": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.4.1.tgz",
- "integrity": "sha512-w6YJMn5DlzmxjO00i9wu2YSozUYRBhIoJ6nQwpMYcBMtiqMGJm1QBzOf6DDgRao8dbtpDoaqLg6iiQTvv0UHhQ==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.1.tgz",
+ "integrity": "sha512-o319vIf5pEMx0LmzSxxkYYxo4wrRLKHq9dP1yJU7FoPTB0LfAKSz8SWD6D/6U3v/O52t9cF5t+MeJiRsfk7zMw==",
"dev": true,
"dependencies": {
- "jest-get-type": "^29.2.0"
+ "jest-get-type": "^29.4.3"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/fake-timers": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.4.1.tgz",
- "integrity": "sha512-/1joI6rfHFmmm39JxNfmNAO3Nwm6Y0VoL5fJDy7H1AtWrD1CgRtqJbN9Ld6rhAkGO76qqp4cwhhxJ9o9kYjQMw==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.1.tgz",
+ "integrity": "sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg==",
"dev": true,
"dependencies": {
- "@jest/types": "^29.4.1",
+ "@jest/types": "^29.6.1",
"@sinonjs/fake-timers": "^10.0.2",
"@types/node": "*",
- "jest-message-util": "^29.4.1",
- "jest-mock": "^29.4.1",
- "jest-util": "^29.4.1"
+ "jest-message-util": "^29.6.1",
+ "jest-mock": "^29.6.1",
+ "jest-util": "^29.6.1"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/globals": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.4.1.tgz",
- "integrity": "sha512-znoK2EuFytbHH0ZSf2mQK2K1xtIgmaw4Da21R2C/NE/+NnItm5mPEFQmn8gmF3f0rfOlmZ3Y3bIf7bFj7DHxAA==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.1.tgz",
+ "integrity": "sha512-2VjpaGy78JY9n9370H8zGRCFbYVWwjY6RdDMhoJHa1sYfwe6XM/azGN0SjY8kk7BOZApIejQ1BFPyH7FPG0w3A==",
"dev": true,
"dependencies": {
- "@jest/environment": "^29.4.1",
- "@jest/expect": "^29.4.1",
- "@jest/types": "^29.4.1",
- "jest-mock": "^29.4.1"
+ "@jest/environment": "^29.6.1",
+ "@jest/expect": "^29.6.1",
+ "@jest/types": "^29.6.1",
+ "jest-mock": "^29.6.1"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/reporters": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.4.1.tgz",
- "integrity": "sha512-AISY5xpt2Xpxj9R6y0RF1+O6GRy9JsGa8+vK23Lmzdy1AYcpQn5ItX79wJSsTmfzPKSAcsY1LNt/8Y5Xe5LOSg==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.1.tgz",
+ "integrity": "sha512-9zuaI9QKr9JnoZtFQlw4GREQbxgmNYXU6QuWtmuODvk5nvPUeBYapVR/VYMyi2WSx3jXTLJTJji8rN6+Cm4+FA==",
"dev": true,
"dependencies": {
"@bcoe/v8-coverage": "^0.2.3",
- "@jest/console": "^29.4.1",
- "@jest/test-result": "^29.4.1",
- "@jest/transform": "^29.4.1",
- "@jest/types": "^29.4.1",
- "@jridgewell/trace-mapping": "^0.3.15",
+ "@jest/console": "^29.6.1",
+ "@jest/test-result": "^29.6.1",
+ "@jest/transform": "^29.6.1",
+ "@jest/types": "^29.6.1",
+ "@jridgewell/trace-mapping": "^0.3.18",
"@types/node": "*",
"chalk": "^4.0.0",
"collect-v8-coverage": "^1.0.0",
@@ -818,9 +815,9 @@
"istanbul-lib-report": "^3.0.0",
"istanbul-lib-source-maps": "^4.0.0",
"istanbul-reports": "^3.1.3",
- "jest-message-util": "^29.4.1",
- "jest-util": "^29.4.1",
- "jest-worker": "^29.4.1",
+ "jest-message-util": "^29.6.1",
+ "jest-util": "^29.6.1",
+ "jest-worker": "^29.6.1",
"slash": "^3.0.0",
"string-length": "^4.0.1",
"strip-ansi": "^6.0.0",
@@ -838,35 +835,25 @@
}
}
},
- "node_modules/@jest/reporters/node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.17",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
- "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
- "dev": true,
- "dependencies": {
- "@jridgewell/resolve-uri": "3.1.0",
- "@jridgewell/sourcemap-codec": "1.4.14"
- }
- },
"node_modules/@jest/schemas": {
- "version": "29.4.0",
- "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.0.tgz",
- "integrity": "sha512-0E01f/gOZeNTG76i5eWWSupvSHaIINrTie7vCyjiYFKgzNdyEGd12BUv4oNBFHOqlHDbtoJi3HrQ38KCC90NsQ==",
+ "version": "29.6.0",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz",
+ "integrity": "sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==",
"dev": true,
"dependencies": {
- "@sinclair/typebox": "^0.25.16"
+ "@sinclair/typebox": "^0.27.8"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/source-map": {
- "version": "29.2.0",
- "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.2.0.tgz",
- "integrity": "sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ==",
+ "version": "29.6.0",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz",
+ "integrity": "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==",
"dev": true,
"dependencies": {
- "@jridgewell/trace-mapping": "^0.3.15",
+ "@jridgewell/trace-mapping": "^0.3.18",
"callsites": "^3.0.0",
"graceful-fs": "^4.2.9"
},
@@ -874,24 +861,14 @@
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@jest/source-map/node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.17",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
- "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
- "dev": true,
- "dependencies": {
- "@jridgewell/resolve-uri": "3.1.0",
- "@jridgewell/sourcemap-codec": "1.4.14"
- }
- },
"node_modules/@jest/test-result": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.4.1.tgz",
- "integrity": "sha512-WRt29Lwt+hEgfN8QDrXqXGgCTidq1rLyFqmZ4lmJOpVArC8daXrZWkWjiaijQvgd3aOUj2fM8INclKHsQW9YyQ==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.1.tgz",
+ "integrity": "sha512-Ynr13ZRcpX6INak0TPUukU8GWRfm/vAytE3JbJNGAvINySWYdfE7dGZMbk36oVuK4CigpbhMn8eg1dixZ7ZJOw==",
"dev": true,
"dependencies": {
- "@jest/console": "^29.4.1",
- "@jest/types": "^29.4.1",
+ "@jest/console": "^29.6.1",
+ "@jest/types": "^29.6.1",
"@types/istanbul-lib-coverage": "^2.0.0",
"collect-v8-coverage": "^1.0.0"
},
@@ -900,14 +877,14 @@
}
},
"node_modules/@jest/test-sequencer": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.4.1.tgz",
- "integrity": "sha512-v5qLBNSsM0eHzWLXsQ5fiB65xi49A3ILPSFQKPXzGL4Vyux0DPZAIN7NAFJa9b4BiTDP9MBF/Zqc/QA1vuiJ0w==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.1.tgz",
+ "integrity": "sha512-oBkC36PCDf/wb6dWeQIhaviU0l5u6VCsXa119yqdUosYAt7/FbQU2M2UoziO3igj/HBDEgp57ONQ3fm0v9uyyg==",
"dev": true,
"dependencies": {
- "@jest/test-result": "^29.4.1",
+ "@jest/test-result": "^29.6.1",
"graceful-fs": "^4.2.9",
- "jest-haste-map": "^29.4.1",
+ "jest-haste-map": "^29.6.1",
"slash": "^3.0.0"
},
"engines": {
@@ -915,48 +892,38 @@
}
},
"node_modules/@jest/transform": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.4.1.tgz",
- "integrity": "sha512-5w6YJrVAtiAgr0phzKjYd83UPbCXsBRTeYI4BXokv9Er9CcrH9hfXL/crCvP2d2nGOcovPUnlYiLPFLZrkG5Hg==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.1.tgz",
+ "integrity": "sha512-URnTneIU3ZjRSaf906cvf6Hpox3hIeJXRnz3VDSw5/X93gR8ycdfSIEy19FlVx8NFmpN7fe3Gb1xF+NjXaQLWg==",
"dev": true,
"dependencies": {
"@babel/core": "^7.11.6",
- "@jest/types": "^29.4.1",
- "@jridgewell/trace-mapping": "^0.3.15",
+ "@jest/types": "^29.6.1",
+ "@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.4.1",
- "jest-regex-util": "^29.2.0",
- "jest-util": "^29.4.1",
+ "jest-haste-map": "^29.6.1",
+ "jest-regex-util": "^29.4.3",
+ "jest-util": "^29.6.1",
"micromatch": "^4.0.4",
"pirates": "^4.0.4",
"slash": "^3.0.0",
- "write-file-atomic": "^5.0.0"
+ "write-file-atomic": "^4.0.2"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/@jest/transform/node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.17",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
- "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
- "dev": true,
- "dependencies": {
- "@jridgewell/resolve-uri": "3.1.0",
- "@jridgewell/sourcemap-codec": "1.4.14"
- }
- },
"node_modules/@jest/types": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.4.1.tgz",
- "integrity": "sha512-zbrAXDUOnpJ+FMST2rV7QZOgec8rskg2zv8g2ajeqitp4tvZiyqTCYXANrKsM+ryj5o+LI+ZN2EgU9drrkiwSA==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz",
+ "integrity": "sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==",
"dev": true,
"dependencies": {
- "@jest/schemas": "^29.4.0",
+ "@jest/schemas": "^29.6.0",
"@types/istanbul-lib-coverage": "^2.0.0",
"@types/istanbul-reports": "^3.0.0",
"@types/node": "*",
@@ -968,13 +935,14 @@
}
},
"node_modules/@jridgewell/gen-mapping": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
- "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==",
+ "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.0",
- "@jridgewell/sourcemap-codec": "^1.4.10"
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
},
"engines": {
"node": ">=6.0.0"
@@ -999,43 +967,49 @@
}
},
"node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.4.14",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
- "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+ "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.9",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
- "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "version": "0.3.18",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz",
+ "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==",
"dev": true,
"dependencies": {
- "@jridgewell/resolve-uri": "^3.0.3",
- "@jridgewell/sourcemap-codec": "^1.4.10"
+ "@jridgewell/resolve-uri": "3.1.0",
+ "@jridgewell/sourcemap-codec": "1.4.14"
}
},
+ "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.14",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+ "dev": true
+ },
"node_modules/@sinclair/typebox": {
- "version": "0.25.21",
- "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.21.tgz",
- "integrity": "sha512-gFukHN4t8K4+wVC+ECqeqwzBDeFeTzBXroBTqE6vcWrQGbEUpHO7LYdG0f4xnvYq4VOEwITSlHlp0JBAIFMS/g==",
+ "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": "2.0.0",
- "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz",
- "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==",
+ "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.0.2",
- "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz",
- "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==",
+ "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": "^2.0.0"
+ "@sinonjs/commons": "^3.0.0"
}
},
"node_modules/@tsconfig/node10": {
@@ -1057,9 +1031,9 @@
"dev": true
},
"node_modules/@tsconfig/node16": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
- "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
+ "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
"dev": true
},
"node_modules/@types/adm-zip": {
@@ -1072,9 +1046,9 @@
}
},
"node_modules/@types/babel__core": {
- "version": "7.20.0",
- "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz",
- "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==",
+ "version": "7.20.1",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz",
+ "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==",
"dev": true,
"dependencies": {
"@babel/parser": "^7.20.7",
@@ -1104,12 +1078,12 @@
}
},
"node_modules/@types/babel__traverse": {
- "version": "7.18.3",
- "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz",
- "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==",
+ "version": "7.20.1",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz",
+ "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==",
"dev": true,
"dependencies": {
- "@babel/types": "^7.3.0"
+ "@babel/types": "^7.20.7"
}
},
"node_modules/@types/graceful-fs": {
@@ -1146,9 +1120,9 @@
}
},
"node_modules/@types/jest": {
- "version": "29.4.0",
- "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.4.0.tgz",
- "integrity": "sha512-VaywcGQ9tPorCX/Jkkni7RWGFfI11whqzs8dvxF41P17Z+z872thvEvlIbznjPJ02kl1HMX3LmLOonsj2n7HeQ==",
+ "version": "29.5.3",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.3.tgz",
+ "integrity": "sha512-1Nq7YrO/vJE/FYnqYyw0FS8LdrjExSgIiHyKg7xPpn+yi8Q4huZryKnkJatN1ZRH89Kw2v33/8ZMB7DuZeSLlA==",
"dev": true,
"dependencies": {
"expect": "^29.0.0",
@@ -1156,15 +1130,15 @@
}
},
"node_modules/@types/node": {
- "version": "18.11.18",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz",
- "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==",
+ "version": "18.16.19",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.19.tgz",
+ "integrity": "sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA==",
"dev": true
},
"node_modules/@types/prettier": {
- "version": "2.7.2",
- "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz",
- "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==",
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz",
+ "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==",
"dev": true
},
"node_modules/@types/stack-utils": {
@@ -1174,9 +1148,9 @@
"dev": true
},
"node_modules/@types/yargs": {
- "version": "17.0.20",
- "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.20.tgz",
- "integrity": "sha512-eknWrTHofQuPk2iuqDm1waA7V6xPlbgBoaaXEgYkClhLOnB0TtbW+srJaOToAgawPxPlHQzwypFA2bhZaUGP5A==",
+ "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": "*"
@@ -1189,9 +1163,9 @@
"dev": true
},
"node_modules/acorn": {
- "version": "8.8.2",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
- "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
+ "version": "8.10.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
+ "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
"dev": true,
"bin": {
"acorn": "bin/acorn"
@@ -1285,9 +1259,9 @@
}
},
"node_modules/aws-cdk-lib": {
- "version": "2.63.0",
- "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.63.0.tgz",
- "integrity": "sha512-+thToi/7coSufwaEafgofTaZERXxFUeEwEIp0SGU0wHz6IbPll5yAzoEIkE51kM8AMCMfqwJddYOjM3qs43cPg==",
+ "version": "2.87.0",
+ "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.87.0.tgz",
+ "integrity": "sha512-9kirXX7L7OP/yGmCbaYlkt5OAtowGiGw0AYFIQvSwvx/UU3aJO5XuDwAgDsvToDkRpBi0yX0bNwqa0DItu+C6A==",
"bundleDependencies": [
"@balena/dockerignore",
"case",
@@ -1297,20 +1271,22 @@
"minimatch",
"punycode",
"semver",
+ "table",
"yaml"
],
"dependencies": {
- "@aws-cdk/asset-awscli-v1": "^2.2.52",
+ "@aws-cdk/asset-awscli-v1": "^2.2.177",
"@aws-cdk/asset-kubectl-v20": "^2.1.1",
- "@aws-cdk/asset-node-proxy-agent-v5": "^2.0.42",
+ "@aws-cdk/asset-node-proxy-agent-v5": "^2.0.148",
"@balena/dockerignore": "^1.0.2",
"case": "1.6.3",
- "fs-extra": "^9.1.0",
+ "fs-extra": "^11.1.1",
"ignore": "^5.2.4",
"jsonschema": "^1.4.1",
"minimatch": "^3.1.2",
"punycode": "^2.3.0",
- "semver": "^7.3.8",
+ "semver": "^7.5.1",
+ "table": "^6.8.1",
"yaml": "1.10.2"
},
"engines": {
@@ -1325,12 +1301,49 @@
"inBundle": true,
"license": "Apache-2.0"
},
- "node_modules/aws-cdk-lib/node_modules/at-least-node": {
- "version": "1.0.0",
+ "node_modules/aws-cdk-lib/node_modules/ajv": {
+ "version": "8.12.0",
"inBundle": true,
- "license": "ISC",
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/astral-regex": {
+ "version": "2.0.0",
+ "inBundle": true,
+ "license": "MIT",
"engines": {
- "node": ">= 4.0.0"
+ "node": ">=8"
}
},
"node_modules/aws-cdk-lib/node_modules/balanced-match": {
@@ -1355,27 +1368,52 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/aws-cdk-lib/node_modules/color-convert": {
+ "version": "2.0.1",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/color-name": {
+ "version": "1.1.4",
+ "inBundle": true,
+ "license": "MIT"
+ },
"node_modules/aws-cdk-lib/node_modules/concat-map": {
"version": "0.0.1",
"inBundle": true,
"license": "MIT"
},
+ "node_modules/aws-cdk-lib/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/aws-cdk-lib/node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "inBundle": true,
+ "license": "MIT"
+ },
"node_modules/aws-cdk-lib/node_modules/fs-extra": {
- "version": "9.1.0",
+ "version": "11.1.1",
"inBundle": true,
"license": "MIT",
"dependencies": {
- "at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
},
"engines": {
- "node": ">=10"
+ "node": ">=14.14"
}
},
"node_modules/aws-cdk-lib/node_modules/graceful-fs": {
- "version": "4.2.10",
+ "version": "4.2.11",
"inBundle": true,
"license": "ISC"
},
@@ -1387,6 +1425,19 @@
"node": ">= 4"
}
},
+ "node_modules/aws-cdk-lib/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "inBundle": true,
+ "license": "MIT"
+ },
"node_modules/aws-cdk-lib/node_modules/jsonfile": {
"version": "6.1.0",
"inBundle": true,
@@ -1406,6 +1457,11 @@
"node": "*"
}
},
+ "node_modules/aws-cdk-lib/node_modules/lodash.truncate": {
+ "version": "4.4.2",
+ "inBundle": true,
+ "license": "MIT"
+ },
"node_modules/aws-cdk-lib/node_modules/lru-cache": {
"version": "6.0.0",
"inBundle": true,
@@ -1436,8 +1492,16 @@
"node": ">=6"
}
},
+ "node_modules/aws-cdk-lib/node_modules/require-from-string": {
+ "version": "2.0.2",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/aws-cdk-lib/node_modules/semver": {
- "version": "7.3.8",
+ "version": "7.5.2",
"inBundle": true,
"license": "ISC",
"dependencies": {
@@ -1450,6 +1514,61 @@
"node": ">=10"
}
},
+ "node_modules/aws-cdk-lib/node_modules/slice-ansi": {
+ "version": "4.0.0",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/string-width": {
+ "version": "4.2.3",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/table": {
+ "version": "6.8.1",
+ "inBundle": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "ajv": "^8.0.1",
+ "lodash.truncate": "^4.4.2",
+ "slice-ansi": "^4.0.0",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
"node_modules/aws-cdk-lib/node_modules/universalify": {
"version": "2.0.0",
"inBundle": true,
@@ -1458,6 +1577,14 @@
"node": ">= 10.0.0"
}
},
+ "node_modules/aws-cdk-lib/node_modules/uri-js": {
+ "version": "4.4.1",
+ "inBundle": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
"node_modules/aws-cdk-lib/node_modules/yallist": {
"version": "4.0.0",
"inBundle": true,
@@ -1472,15 +1599,15 @@
}
},
"node_modules/babel-jest": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.4.1.tgz",
- "integrity": "sha512-xBZa/pLSsF/1sNpkgsiT3CmY7zV1kAsZ9OxxtrFqYucnOuRftXAfcJqcDVyOPeN4lttWTwhLdu0T9f8uvoPEUg==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.1.tgz",
+ "integrity": "sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A==",
"dev": true,
"dependencies": {
- "@jest/transform": "^29.4.1",
+ "@jest/transform": "^29.6.1",
"@types/babel__core": "^7.1.14",
"babel-plugin-istanbul": "^6.1.1",
- "babel-preset-jest": "^29.4.0",
+ "babel-preset-jest": "^29.5.0",
"chalk": "^4.0.0",
"graceful-fs": "^4.2.9",
"slash": "^3.0.0"
@@ -1509,9 +1636,9 @@
}
},
"node_modules/babel-plugin-jest-hoist": {
- "version": "29.4.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.4.0.tgz",
- "integrity": "sha512-a/sZRLQJEmsmejQ2rPEUe35nO1+C9dc9O1gplH1SXmJxveQSRUYdBk8yGZG/VOUuZs1u2aHZJusEGoRMbhhwCg==",
+ "version": "29.5.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz",
+ "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==",
"dev": true,
"dependencies": {
"@babel/template": "^7.3.3",
@@ -1547,12 +1674,12 @@
}
},
"node_modules/babel-preset-jest": {
- "version": "29.4.0",
- "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.4.0.tgz",
- "integrity": "sha512-fUB9vZflUSM3dO/6M2TCAepTzvA4VkOvl67PjErcrQMGt9Eve7uazaeyCZ2th3UtI7ljpiBJES0F7A1vBRsLZA==",
+ "version": "29.5.0",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz",
+ "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==",
"dev": true,
"dependencies": {
- "babel-plugin-jest-hoist": "^29.4.0",
+ "babel-plugin-jest-hoist": "^29.5.0",
"babel-preset-current-node-syntax": "^1.0.0"
},
"engines": {
@@ -1565,14 +1692,12 @@
"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
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"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"
@@ -1591,9 +1716,9 @@
}
},
"node_modules/browserslist": {
- "version": "4.21.4",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
- "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==",
+ "version": "4.21.9",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz",
+ "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==",
"dev": true,
"funding": [
{
@@ -1603,13 +1728,17 @@
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
- "caniuse-lite": "^1.0.30001400",
- "electron-to-chromium": "^1.4.251",
- "node-releases": "^2.0.6",
- "update-browserslist-db": "^1.0.9"
+ "caniuse-lite": "^1.0.30001503",
+ "electron-to-chromium": "^1.4.431",
+ "node-releases": "^2.0.12",
+ "update-browserslist-db": "^1.0.11"
},
"bin": {
"browserslist": "cli.js"
@@ -1664,9 +1793,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001449",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001449.tgz",
- "integrity": "sha512-CPB+UL9XMT/Av+pJxCKGhdx+yg1hzplvFJQlJ2n68PyQGMz9L/E2zCyLdOL8uasbouTUgnPl+y0tccI/se+BEw==",
+ "version": "1.0.30001516",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001516.tgz",
+ "integrity": "sha512-Wmec9pCBY8CWbmI4HsjBeQLqDTqV91nFVR83DnZpYyRnPI1wePDsTg0bGLPC5VU/3OIZV1fmxEea1b+tFKe86g==",
"dev": true,
"funding": [
{
@@ -1676,6 +1805,10 @@
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
}
]
},
@@ -1705,9 +1838,9 @@
}
},
"node_modules/ci-info": {
- "version": "3.7.1",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.1.tgz",
- "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==",
+ "version": "3.8.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz",
+ "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==",
"dev": true,
"funding": [
{
@@ -1720,9 +1853,9 @@
}
},
"node_modules/cjs-module-lexer": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz",
- "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==",
+ "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/cliui": {
@@ -1750,9 +1883,9 @@
}
},
"node_modules/collect-v8-coverage": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz",
- "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==",
+ "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": {
@@ -1776,16 +1909,15 @@
"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
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
"node_modules/constructs": {
- "version": "10.1.236",
- "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.1.236.tgz",
- "integrity": "sha512-JBikdlmN5sKDjwZmPPoveNr7K6N7SQLBEJY83r3Px86CGyMu0YXtaYpjFg2fQd9zs8X77QnyNzb54SKiicSD9g==",
+ "version": "10.2.69",
+ "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.2.69.tgz",
+ "integrity": "sha512-0AiM/uQe5Uk6JVe/62oolmSN2MjbFQkOlYrM3fFGZLKuT+g7xlAI10EebFhyCcZwI2JAcWuWCmmCAyCothxjuw==",
"peer": true,
"engines": {
- "node": ">= 14.17.0"
+ "node": ">= 16.14.0"
}
},
"node_modules/convert-source-map": {
@@ -1838,9 +1970,9 @@
"dev": true
},
"node_modules/deepmerge": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
- "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
+ "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"
@@ -1865,18 +1997,18 @@
}
},
"node_modules/diff-sequences": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.3.1.tgz",
- "integrity": "sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==",
+ "version": "29.4.3",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz",
+ "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==",
"dev": true,
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/electron-to-chromium": {
- "version": "1.4.284",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz",
- "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==",
+ "version": "1.4.462",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.462.tgz",
+ "integrity": "sha512-ux2LqN9JKRBDKXMT+78jtiBLPiXf+rLtYlsrOg5Qn7uv6Cbg7+9JyIalE3wcqkOdB2wPCUYNWAuL7suKRMHe9w==",
"dev": true
},
"node_modules/emittery": {
@@ -1970,16 +2102,17 @@
}
},
"node_modules/expect": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/expect/-/expect-29.4.1.tgz",
- "integrity": "sha512-OKrGESHOaMxK3b6zxIq9SOW8kEXztKff/Dvg88j4xIJxur1hspEbedVkR3GpHe5LO+WB2Qw7OWN0RMTdp6as5A==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.1.tgz",
+ "integrity": "sha512-XEdDLonERCU1n9uR56/Stx9OqojaLAQtZf9PrCHH9Hl8YXiEIka3H4NXJ3NOIBmQJTg7+j7buh34PMHfJujc8g==",
"dev": true,
"dependencies": {
- "@jest/expect-utils": "^29.4.1",
- "jest-get-type": "^29.2.0",
- "jest-matcher-utils": "^29.4.1",
- "jest-message-util": "^29.4.1",
- "jest-util": "^29.4.1"
+ "@jest/expect-utils": "^29.6.1",
+ "@types/node": "*",
+ "jest-get-type": "^29.4.3",
+ "jest-matcher-utils": "^29.6.1",
+ "jest-message-util": "^29.6.1",
+ "jest-util": "^29.6.1"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -2120,9 +2253,9 @@
}
},
"node_modules/graceful-fs": {
- "version": "4.2.10",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
- "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "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": {
@@ -2212,9 +2345,9 @@
"dev": true
},
"node_modules/is-core-module": {
- "version": "2.11.0",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
- "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
+ "version": "2.12.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz",
+ "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==",
"dev": true,
"dependencies": {
"has": "^1.0.3"
@@ -2335,15 +2468,15 @@
}
},
"node_modules/jest": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest/-/jest-29.4.1.tgz",
- "integrity": "sha512-cknimw7gAXPDOmj0QqztlxVtBVCw2lYY9CeIE5N6kD+kET1H4H79HSNISJmijb1HF+qk+G+ploJgiDi5k/fRlg==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.1.tgz",
+ "integrity": "sha512-Nirw5B4nn69rVUZtemCQhwxOBhm0nsp3hmtF4rzCeWD7BkjAXRIji7xWQfnTNbz9g0aVsBX6aZK3n+23LM6uDw==",
"dev": true,
"dependencies": {
- "@jest/core": "^29.4.1",
- "@jest/types": "^29.4.1",
+ "@jest/core": "^29.6.1",
+ "@jest/types": "^29.6.1",
"import-local": "^3.0.2",
- "jest-cli": "^29.4.1"
+ "jest-cli": "^29.6.1"
},
"bin": {
"jest": "bin/jest.js"
@@ -2361,9 +2494,9 @@
}
},
"node_modules/jest-changed-files": {
- "version": "29.4.0",
- "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.4.0.tgz",
- "integrity": "sha512-rnI1oPxgFghoz32Y8eZsGJMjW54UlqT17ycQeCEktcxxwqqKdlj9afl8LNeO0Pbu+h2JQHThQP0BzS67eTRx4w==",
+ "version": "29.5.0",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz",
+ "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==",
"dev": true,
"dependencies": {
"execa": "^5.0.0",
@@ -2374,28 +2507,29 @@
}
},
"node_modules/jest-circus": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.4.1.tgz",
- "integrity": "sha512-v02NuL5crMNY4CGPHBEflLzl4v91NFb85a+dH9a1pUNx6Xjggrd8l9pPy4LZ1VYNRXlb+f65+7O/MSIbLir6pA==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.1.tgz",
+ "integrity": "sha512-tPbYLEiBU4MYAL2XoZme/bgfUeotpDBd81lgHLCbDZZFaGmECk0b+/xejPFtmiBP87GgP/y4jplcRpbH+fgCzQ==",
"dev": true,
"dependencies": {
- "@jest/environment": "^29.4.1",
- "@jest/expect": "^29.4.1",
- "@jest/test-result": "^29.4.1",
- "@jest/types": "^29.4.1",
+ "@jest/environment": "^29.6.1",
+ "@jest/expect": "^29.6.1",
+ "@jest/test-result": "^29.6.1",
+ "@jest/types": "^29.6.1",
"@types/node": "*",
"chalk": "^4.0.0",
"co": "^4.6.0",
"dedent": "^0.7.0",
"is-generator-fn": "^2.0.0",
- "jest-each": "^29.4.1",
- "jest-matcher-utils": "^29.4.1",
- "jest-message-util": "^29.4.1",
- "jest-runtime": "^29.4.1",
- "jest-snapshot": "^29.4.1",
- "jest-util": "^29.4.1",
+ "jest-each": "^29.6.1",
+ "jest-matcher-utils": "^29.6.1",
+ "jest-message-util": "^29.6.1",
+ "jest-runtime": "^29.6.1",
+ "jest-snapshot": "^29.6.1",
+ "jest-util": "^29.6.1",
"p-limit": "^3.1.0",
- "pretty-format": "^29.4.1",
+ "pretty-format": "^29.6.1",
+ "pure-rand": "^6.0.0",
"slash": "^3.0.0",
"stack-utils": "^2.0.3"
},
@@ -2404,21 +2538,21 @@
}
},
"node_modules/jest-cli": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.4.1.tgz",
- "integrity": "sha512-jz7GDIhtxQ37M+9dlbv5K+/FVcIo1O/b1sX3cJgzlQUf/3VG25nvuWzlDC4F1FLLzUThJeWLu8I7JF9eWpuURQ==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.1.tgz",
+ "integrity": "sha512-607dSgTA4ODIN6go9w6xY3EYkyPFGicx51a69H7yfvt7lN53xNswEVLovq+E77VsTRi5fWprLH0yl4DJgE8Ing==",
"dev": true,
"dependencies": {
- "@jest/core": "^29.4.1",
- "@jest/test-result": "^29.4.1",
- "@jest/types": "^29.4.1",
+ "@jest/core": "^29.6.1",
+ "@jest/test-result": "^29.6.1",
+ "@jest/types": "^29.6.1",
"chalk": "^4.0.0",
"exit": "^0.1.2",
"graceful-fs": "^4.2.9",
"import-local": "^3.0.2",
- "jest-config": "^29.4.1",
- "jest-util": "^29.4.1",
- "jest-validate": "^29.4.1",
+ "jest-config": "^29.6.1",
+ "jest-util": "^29.6.1",
+ "jest-validate": "^29.6.1",
"prompts": "^2.0.1",
"yargs": "^17.3.1"
},
@@ -2438,31 +2572,31 @@
}
},
"node_modules/jest-config": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.4.1.tgz",
- "integrity": "sha512-g7p3q4NuXiM4hrS4XFATTkd+2z0Ml2RhFmFPM8c3WyKwVDNszbl4E7cV7WIx1YZeqqCtqbtTtZhGZWJlJqngzg==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.1.tgz",
+ "integrity": "sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ==",
"dev": true,
"dependencies": {
"@babel/core": "^7.11.6",
- "@jest/test-sequencer": "^29.4.1",
- "@jest/types": "^29.4.1",
- "babel-jest": "^29.4.1",
+ "@jest/test-sequencer": "^29.6.1",
+ "@jest/types": "^29.6.1",
+ "babel-jest": "^29.6.1",
"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.4.1",
- "jest-environment-node": "^29.4.1",
- "jest-get-type": "^29.2.0",
- "jest-regex-util": "^29.2.0",
- "jest-resolve": "^29.4.1",
- "jest-runner": "^29.4.1",
- "jest-util": "^29.4.1",
- "jest-validate": "^29.4.1",
+ "jest-circus": "^29.6.1",
+ "jest-environment-node": "^29.6.1",
+ "jest-get-type": "^29.4.3",
+ "jest-regex-util": "^29.4.3",
+ "jest-resolve": "^29.6.1",
+ "jest-runner": "^29.6.1",
+ "jest-util": "^29.6.1",
+ "jest-validate": "^29.6.1",
"micromatch": "^4.0.4",
"parse-json": "^5.2.0",
- "pretty-format": "^29.4.1",
+ "pretty-format": "^29.6.1",
"slash": "^3.0.0",
"strip-json-comments": "^3.1.1"
},
@@ -2483,24 +2617,24 @@
}
},
"node_modules/jest-diff": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.4.1.tgz",
- "integrity": "sha512-uazdl2g331iY56CEyfbNA0Ut7Mn2ulAG5vUaEHXycf1L6IPyuImIxSz4F0VYBKi7LYIuxOwTZzK3wh5jHzASMw==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.1.tgz",
+ "integrity": "sha512-FsNCvinvl8oVxpNLttNQX7FAq7vR+gMDGj90tiP7siWw1UdakWUGqrylpsYrpvj908IYckm5Y0Q7azNAozU1Kg==",
"dev": true,
"dependencies": {
"chalk": "^4.0.0",
- "diff-sequences": "^29.3.1",
- "jest-get-type": "^29.2.0",
- "pretty-format": "^29.4.1"
+ "diff-sequences": "^29.4.3",
+ "jest-get-type": "^29.4.3",
+ "pretty-format": "^29.6.1"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-docblock": {
- "version": "29.2.0",
- "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.2.0.tgz",
- "integrity": "sha512-bkxUsxTgWQGbXV5IENmfiIuqZhJcyvF7tU4zJ/7ioTutdz4ToB5Yx6JOFBpgI+TphRY4lhOyCWGNH/QFQh5T6A==",
+ "version": "29.4.3",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz",
+ "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==",
"dev": true,
"dependencies": {
"detect-newline": "^3.0.0"
@@ -2510,62 +2644,62 @@
}
},
"node_modules/jest-each": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.4.1.tgz",
- "integrity": "sha512-QlYFiX3llJMWUV0BtWht/esGEz9w+0i7BHwODKCze7YzZzizgExB9MOfiivF/vVT0GSQ8wXLhvHXh3x2fVD4QQ==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.1.tgz",
+ "integrity": "sha512-n5eoj5eiTHpKQCAVcNTT7DRqeUmJ01hsAL0Q1SMiBHcBcvTKDELixQOGMCpqhbIuTcfC4kMfSnpmDqRgRJcLNQ==",
"dev": true,
"dependencies": {
- "@jest/types": "^29.4.1",
+ "@jest/types": "^29.6.1",
"chalk": "^4.0.0",
- "jest-get-type": "^29.2.0",
- "jest-util": "^29.4.1",
- "pretty-format": "^29.4.1"
+ "jest-get-type": "^29.4.3",
+ "jest-util": "^29.6.1",
+ "pretty-format": "^29.6.1"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-environment-node": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.4.1.tgz",
- "integrity": "sha512-x/H2kdVgxSkxWAIlIh9MfMuBa0hZySmfsC5lCsWmWr6tZySP44ediRKDUiNggX/eHLH7Cd5ZN10Rw+XF5tXsqg==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.1.tgz",
+ "integrity": "sha512-ZNIfAiE+foBog24W+2caIldl4Irh8Lx1PUhg/GZ0odM1d/h2qORAsejiFc7zb+SEmYPn1yDZzEDSU5PmDkmVLQ==",
"dev": true,
"dependencies": {
- "@jest/environment": "^29.4.1",
- "@jest/fake-timers": "^29.4.1",
- "@jest/types": "^29.4.1",
+ "@jest/environment": "^29.6.1",
+ "@jest/fake-timers": "^29.6.1",
+ "@jest/types": "^29.6.1",
"@types/node": "*",
- "jest-mock": "^29.4.1",
- "jest-util": "^29.4.1"
+ "jest-mock": "^29.6.1",
+ "jest-util": "^29.6.1"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-get-type": {
- "version": "29.2.0",
- "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz",
- "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==",
+ "version": "29.4.3",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz",
+ "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==",
"dev": true,
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-haste-map": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.4.1.tgz",
- "integrity": "sha512-imTjcgfVVTvg02khXL11NNLTx9ZaofbAWhilrMg/G8dIkp+HYCswhxf0xxJwBkfhWb3e8dwbjuWburvxmcr58w==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.1.tgz",
+ "integrity": "sha512-0m7f9PZXxOCk1gRACiVgX85knUKPKLPg4oRCjLoqIm9brTHXaorMA0JpmtmVkQiT8nmXyIVoZd/nnH1cfC33ig==",
"dev": true,
"dependencies": {
- "@jest/types": "^29.4.1",
+ "@jest/types": "^29.6.1",
"@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.2.0",
- "jest-util": "^29.4.1",
- "jest-worker": "^29.4.1",
+ "jest-regex-util": "^29.4.3",
+ "jest-util": "^29.6.1",
+ "jest-worker": "^29.6.1",
"micromatch": "^4.0.4",
"walker": "^1.0.8"
},
@@ -2577,46 +2711,46 @@
}
},
"node_modules/jest-leak-detector": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.4.1.tgz",
- "integrity": "sha512-akpZv7TPyGMnH2RimOCgy+hPmWZf55EyFUvymQ4LMsQP8xSPlZumCPtXGoDhFNhUE2039RApZkTQDKU79p/FiQ==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.1.tgz",
+ "integrity": "sha512-OrxMNyZirpOEwkF3UHnIkAiZbtkBWiye+hhBweCHkVbCgyEy71Mwbb5zgeTNYWJBi1qgDVfPC1IwO9dVEeTLwQ==",
"dev": true,
"dependencies": {
- "jest-get-type": "^29.2.0",
- "pretty-format": "^29.4.1"
+ "jest-get-type": "^29.4.3",
+ "pretty-format": "^29.6.1"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-matcher-utils": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.4.1.tgz",
- "integrity": "sha512-k5h0u8V4nAEy6lSACepxL/rw78FLDkBnXhZVgFneVpnJONhb2DhZj/Gv4eNe+1XqQ5IhgUcqj745UwH0HJmMnA==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.1.tgz",
+ "integrity": "sha512-SLaztw9d2mfQQKHmJXKM0HCbl2PPVld/t9Xa6P9sgiExijviSp7TnZZpw2Fpt+OI3nwUO/slJbOfzfUMKKC5QA==",
"dev": true,
"dependencies": {
"chalk": "^4.0.0",
- "jest-diff": "^29.4.1",
- "jest-get-type": "^29.2.0",
- "pretty-format": "^29.4.1"
+ "jest-diff": "^29.6.1",
+ "jest-get-type": "^29.4.3",
+ "pretty-format": "^29.6.1"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-message-util": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.4.1.tgz",
- "integrity": "sha512-H4/I0cXUaLeCw6FM+i4AwCnOwHRgitdaUFOdm49022YD5nfyr8C/DrbXOBEyJaj+w/y0gGJ57klssOaUiLLQGQ==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.1.tgz",
+ "integrity": "sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ==",
"dev": true,
"dependencies": {
"@babel/code-frame": "^7.12.13",
- "@jest/types": "^29.4.1",
+ "@jest/types": "^29.6.1",
"@types/stack-utils": "^2.0.0",
"chalk": "^4.0.0",
"graceful-fs": "^4.2.9",
"micromatch": "^4.0.4",
- "pretty-format": "^29.4.1",
+ "pretty-format": "^29.6.1",
"slash": "^3.0.0",
"stack-utils": "^2.0.3"
},
@@ -2625,14 +2759,14 @@
}
},
"node_modules/jest-mock": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.4.1.tgz",
- "integrity": "sha512-MwA4hQ7zBOcgVCVnsM8TzaFLVUD/pFWTfbkY953Y81L5ret3GFRZtmPmRFAjKQSdCKoJvvqOu6Bvfpqlwwb0dQ==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.1.tgz",
+ "integrity": "sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw==",
"dev": true,
"dependencies": {
- "@jest/types": "^29.4.1",
+ "@jest/types": "^29.6.1",
"@types/node": "*",
- "jest-util": "^29.4.1"
+ "jest-util": "^29.6.1"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -2656,26 +2790,26 @@
}
},
"node_modules/jest-regex-util": {
- "version": "29.2.0",
- "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.2.0.tgz",
- "integrity": "sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA==",
+ "version": "29.4.3",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz",
+ "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==",
"dev": true,
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-resolve": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.4.1.tgz",
- "integrity": "sha512-j/ZFNV2lm9IJ2wmlq1uYK0Y/1PiyDq9g4HEGsNTNr3viRbJdV+8Lf1SXIiLZXFvyiisu0qUyIXGBnw+OKWkJwQ==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.1.tgz",
+ "integrity": "sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg==",
"dev": true,
"dependencies": {
"chalk": "^4.0.0",
"graceful-fs": "^4.2.9",
- "jest-haste-map": "^29.4.1",
+ "jest-haste-map": "^29.6.1",
"jest-pnp-resolver": "^1.2.2",
- "jest-util": "^29.4.1",
- "jest-validate": "^29.4.1",
+ "jest-util": "^29.6.1",
+ "jest-validate": "^29.6.1",
"resolve": "^1.20.0",
"resolve.exports": "^2.0.0",
"slash": "^3.0.0"
@@ -2685,43 +2819,43 @@
}
},
"node_modules/jest-resolve-dependencies": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.4.1.tgz",
- "integrity": "sha512-Y3QG3M1ncAMxfjbYgtqNXC5B595zmB6e//p/qpA/58JkQXu/IpLDoLeOa8YoYfsSglBKQQzNUqtfGJJT/qLmJg==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.1.tgz",
+ "integrity": "sha512-BbFvxLXtcldaFOhNMXmHRWx1nXQO5LoXiKSGQcA1LxxirYceZT6ch8KTE1bK3X31TNG/JbkI7OkS/ABexVahiw==",
"dev": true,
"dependencies": {
- "jest-regex-util": "^29.2.0",
- "jest-snapshot": "^29.4.1"
+ "jest-regex-util": "^29.4.3",
+ "jest-snapshot": "^29.6.1"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-runner": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.4.1.tgz",
- "integrity": "sha512-8d6XXXi7GtHmsHrnaqBKWxjKb166Eyj/ksSaUYdcBK09VbjPwIgWov1VwSmtupCIz8q1Xv4Qkzt/BTo3ZqiCeg==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.1.tgz",
+ "integrity": "sha512-tw0wb2Q9yhjAQ2w8rHRDxteryyIck7gIzQE4Reu3JuOBpGp96xWgF0nY8MDdejzrLCZKDcp8JlZrBN/EtkQvPQ==",
"dev": true,
"dependencies": {
- "@jest/console": "^29.4.1",
- "@jest/environment": "^29.4.1",
- "@jest/test-result": "^29.4.1",
- "@jest/transform": "^29.4.1",
- "@jest/types": "^29.4.1",
+ "@jest/console": "^29.6.1",
+ "@jest/environment": "^29.6.1",
+ "@jest/test-result": "^29.6.1",
+ "@jest/transform": "^29.6.1",
+ "@jest/types": "^29.6.1",
"@types/node": "*",
"chalk": "^4.0.0",
"emittery": "^0.13.1",
"graceful-fs": "^4.2.9",
- "jest-docblock": "^29.2.0",
- "jest-environment-node": "^29.4.1",
- "jest-haste-map": "^29.4.1",
- "jest-leak-detector": "^29.4.1",
- "jest-message-util": "^29.4.1",
- "jest-resolve": "^29.4.1",
- "jest-runtime": "^29.4.1",
- "jest-util": "^29.4.1",
- "jest-watcher": "^29.4.1",
- "jest-worker": "^29.4.1",
+ "jest-docblock": "^29.4.3",
+ "jest-environment-node": "^29.6.1",
+ "jest-haste-map": "^29.6.1",
+ "jest-leak-detector": "^29.6.1",
+ "jest-message-util": "^29.6.1",
+ "jest-resolve": "^29.6.1",
+ "jest-runtime": "^29.6.1",
+ "jest-util": "^29.6.1",
+ "jest-watcher": "^29.6.1",
+ "jest-worker": "^29.6.1",
"p-limit": "^3.1.0",
"source-map-support": "0.5.13"
},
@@ -2730,32 +2864,31 @@
}
},
"node_modules/jest-runtime": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.4.1.tgz",
- "integrity": "sha512-UXTMU9uKu2GjYwTtoAw5rn4STxWw/nadOfW7v1sx6LaJYa3V/iymdCLQM6xy3+7C6mY8GfX22vKpgxY171UIoA==",
- "dev": true,
- "dependencies": {
- "@jest/environment": "^29.4.1",
- "@jest/fake-timers": "^29.4.1",
- "@jest/globals": "^29.4.1",
- "@jest/source-map": "^29.2.0",
- "@jest/test-result": "^29.4.1",
- "@jest/transform": "^29.4.1",
- "@jest/types": "^29.4.1",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.1.tgz",
+ "integrity": "sha512-D6/AYOA+Lhs5e5il8+5pSLemjtJezUr+8zx+Sn8xlmOux3XOqx4d8l/2udBea8CRPqqrzhsKUsN/gBDE/IcaPQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^29.6.1",
+ "@jest/fake-timers": "^29.6.1",
+ "@jest/globals": "^29.6.1",
+ "@jest/source-map": "^29.6.0",
+ "@jest/test-result": "^29.6.1",
+ "@jest/transform": "^29.6.1",
+ "@jest/types": "^29.6.1",
"@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.4.1",
- "jest-message-util": "^29.4.1",
- "jest-mock": "^29.4.1",
- "jest-regex-util": "^29.2.0",
- "jest-resolve": "^29.4.1",
- "jest-snapshot": "^29.4.1",
- "jest-util": "^29.4.1",
- "semver": "^7.3.5",
+ "jest-haste-map": "^29.6.1",
+ "jest-message-util": "^29.6.1",
+ "jest-mock": "^29.6.1",
+ "jest-regex-util": "^29.4.3",
+ "jest-resolve": "^29.6.1",
+ "jest-snapshot": "^29.6.1",
+ "jest-util": "^29.6.1",
"slash": "^3.0.0",
"strip-bom": "^4.0.0"
},
@@ -2763,69 +2896,33 @@
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/jest-runtime/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-runtime/node_modules/semver": {
- "version": "7.3.8",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
- "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
- "dev": true,
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/jest-runtime/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-snapshot": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.4.1.tgz",
- "integrity": "sha512-l4iV8EjGgQWVz3ee/LR9sULDk2pCkqb71bjvlqn+qp90lFwpnulHj4ZBT8nm1hA1C5wowXLc7MGnw321u0tsYA==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.1.tgz",
+ "integrity": "sha512-G4UQE1QQ6OaCgfY+A0uR1W2AY0tGXUPQpoUClhWHq1Xdnx1H6JOrC2nH5lqnOEqaDgbHFgIwZ7bNq24HpB180A==",
"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/traverse": "^7.7.2",
"@babel/types": "^7.3.3",
- "@jest/expect-utils": "^29.4.1",
- "@jest/transform": "^29.4.1",
- "@jest/types": "^29.4.1",
- "@types/babel__traverse": "^7.0.6",
+ "@jest/expect-utils": "^29.6.1",
+ "@jest/transform": "^29.6.1",
+ "@jest/types": "^29.6.1",
"@types/prettier": "^2.1.5",
"babel-preset-current-node-syntax": "^1.0.0",
"chalk": "^4.0.0",
- "expect": "^29.4.1",
+ "expect": "^29.6.1",
"graceful-fs": "^4.2.9",
- "jest-diff": "^29.4.1",
- "jest-get-type": "^29.2.0",
- "jest-haste-map": "^29.4.1",
- "jest-matcher-utils": "^29.4.1",
- "jest-message-util": "^29.4.1",
- "jest-util": "^29.4.1",
+ "jest-diff": "^29.6.1",
+ "jest-get-type": "^29.4.3",
+ "jest-matcher-utils": "^29.6.1",
+ "jest-message-util": "^29.6.1",
+ "jest-util": "^29.6.1",
"natural-compare": "^1.4.0",
- "pretty-format": "^29.4.1",
- "semver": "^7.3.5"
+ "pretty-format": "^29.6.1",
+ "semver": "^7.5.3"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -2844,9 +2941,9 @@
}
},
"node_modules/jest-snapshot/node_modules/semver": {
- "version": "7.3.8",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
- "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
+ "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"
@@ -2865,12 +2962,12 @@
"dev": true
},
"node_modules/jest-util": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.4.1.tgz",
- "integrity": "sha512-bQy9FPGxVutgpN4VRc0hk6w7Hx/m6L53QxpDreTZgJd9gfx/AV2MjyPde9tGyZRINAUrSv57p2inGBu2dRLmkQ==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.1.tgz",
+ "integrity": "sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg==",
"dev": true,
"dependencies": {
- "@jest/types": "^29.4.1",
+ "@jest/types": "^29.6.1",
"@types/node": "*",
"chalk": "^4.0.0",
"ci-info": "^3.2.0",
@@ -2882,17 +2979,17 @@
}
},
"node_modules/jest-validate": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.4.1.tgz",
- "integrity": "sha512-qNZXcZQdIQx4SfUB/atWnI4/I2HUvhz8ajOSYUu40CSmf9U5emil8EDHgE7M+3j9/pavtk3knlZBDsgFvv/SWw==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.1.tgz",
+ "integrity": "sha512-r3Ds69/0KCN4vx4sYAbGL1EVpZ7MSS0vLmd3gV78O+NAx3PDQQukRU5hNHPXlyqCgFY8XUk7EuTMLugh0KzahA==",
"dev": true,
"dependencies": {
- "@jest/types": "^29.4.1",
+ "@jest/types": "^29.6.1",
"camelcase": "^6.2.0",
"chalk": "^4.0.0",
- "jest-get-type": "^29.2.0",
+ "jest-get-type": "^29.4.3",
"leven": "^3.1.0",
- "pretty-format": "^29.4.1"
+ "pretty-format": "^29.6.1"
},
"engines": {
"node": "^14.15.0 || ^16.10.0 || >=18.0.0"
@@ -2911,18 +3008,18 @@
}
},
"node_modules/jest-watcher": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.4.1.tgz",
- "integrity": "sha512-vFOzflGFs27nU6h8dpnVRER3O2rFtL+VMEwnG0H3KLHcllLsU8y9DchSh0AL/Rg5nN1/wSiQ+P4ByMGpuybaVw==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.1.tgz",
+ "integrity": "sha512-d4wpjWTS7HEZPaaj8m36QiaP856JthRZkrgcIY/7ISoUWPIillrXM23WPboZVLbiwZBt4/qn2Jke84Sla6JhFA==",
"dev": true,
"dependencies": {
- "@jest/test-result": "^29.4.1",
- "@jest/types": "^29.4.1",
+ "@jest/test-result": "^29.6.1",
+ "@jest/types": "^29.6.1",
"@types/node": "*",
"ansi-escapes": "^4.2.1",
"chalk": "^4.0.0",
"emittery": "^0.13.1",
- "jest-util": "^29.4.1",
+ "jest-util": "^29.6.1",
"string-length": "^4.0.1"
},
"engines": {
@@ -2930,13 +3027,13 @@
}
},
"node_modules/jest-worker": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.4.1.tgz",
- "integrity": "sha512-O9doU/S1EBe+yp/mstQ0VpPwpv0Clgn68TkNwGxL6/usX/KUW9Arnn4ag8C3jc6qHcXznhsT5Na1liYzAsuAbQ==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.1.tgz",
+ "integrity": "sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==",
"dev": true,
"dependencies": {
"@types/node": "*",
- "jest-util": "^29.4.1",
+ "jest-util": "^29.6.1",
"merge-stream": "^2.0.0",
"supports-color": "^8.0.0"
},
@@ -3121,7 +3218,6 @@
"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"
},
@@ -3148,9 +3244,9 @@
"dev": true
},
"node_modules/node-releases": {
- "version": "2.0.8",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz",
- "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==",
+ "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": {
@@ -3319,9 +3415,9 @@
}
},
"node_modules/pirates": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz",
- "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==",
+ "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"
@@ -3340,12 +3436,12 @@
}
},
"node_modules/pretty-format": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.4.1.tgz",
- "integrity": "sha512-dt/Z761JUVsrIKaY215o1xQJBGlSmTx/h4cSqXqjHLnU1+Kt+mavVE7UgqJJO5ukx5HjSswHfmXz4LjS2oIJfg==",
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz",
+ "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==",
"dev": true,
"dependencies": {
- "@jest/schemas": "^29.4.0",
+ "@jest/schemas": "^29.6.0",
"ansi-styles": "^5.0.0",
"react-is": "^18.0.0"
},
@@ -3378,6 +3474,22 @@
"node": ">= 6"
}
},
+ "node_modules/pure-rand": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz",
+ "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/dubzzz"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fast-check"
+ }
+ ]
+ },
"node_modules/react-is": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
@@ -3394,12 +3506,12 @@
}
},
"node_modules/resolve": {
- "version": "1.22.1",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
- "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+ "version": "1.22.2",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
+ "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==",
"dev": true,
"dependencies": {
- "is-core-module": "^2.9.0",
+ "is-core-module": "^2.11.0",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
},
@@ -3432,19 +3544,18 @@
}
},
"node_modules/resolve.exports": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.0.tgz",
- "integrity": "sha512-6K/gDlqgQscOlg9fSRpWstA8sYe8rbELsSTNpx+3kTrsVCzvSl0zIvRErM7fdl9ERWDsKnrLnwB+Ne89918XOg==",
+ "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.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
- "dev": true,
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
@@ -3663,9 +3774,9 @@
}
},
"node_modules/ts-jest": {
- "version": "29.0.5",
- "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.5.tgz",
- "integrity": "sha512-PL3UciSgIpQ7f6XjVOmbi96vmDHUqAyqDr8YxzopDqX3kfgYtX1cuNeBjP+L9sFXi6nzsGGA6R3fP3DDDJyrxA==",
+ "version": "29.1.1",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz",
+ "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==",
"dev": true,
"dependencies": {
"bs-logger": "0.x",
@@ -3674,7 +3785,7 @@
"json5": "^2.2.3",
"lodash.memoize": "4.x",
"make-error": "1.x",
- "semver": "7.x",
+ "semver": "^7.5.3",
"yargs-parser": "^21.0.1"
},
"bin": {
@@ -3688,7 +3799,7 @@
"@jest/types": "^29.0.0",
"babel-jest": "^29.0.0",
"jest": "^29.0.0",
- "typescript": ">=4.3"
+ "typescript": ">=4.3 <6"
},
"peerDependenciesMeta": {
"@babel/core": {
@@ -3718,9 +3829,9 @@
}
},
"node_modules/ts-jest/node_modules/semver": {
- "version": "7.3.8",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
- "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
+ "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"
@@ -3803,22 +3914,22 @@
}
},
"node_modules/typescript": {
- "version": "4.9.4",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
- "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==",
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz",
+ "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
- "node": ">=4.2.0"
+ "node": ">=14.17"
}
},
"node_modules/update-browserslist-db": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
- "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==",
+ "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": [
{
@@ -3828,6 +3939,10 @@
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
@@ -3835,7 +3950,7 @@
"picocolors": "^1.0.0"
},
"bin": {
- "browserslist-lint": "cli.js"
+ "update-browserslist-db": "cli.js"
},
"peerDependencies": {
"browserslist": ">= 4.21.0"
@@ -3848,9 +3963,9 @@
"dev": true
},
"node_modules/v8-to-istanbul": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz",
- "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==",
+ "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",
@@ -3861,16 +3976,6 @@
"node": ">=10.12.0"
}
},
- "node_modules/v8-to-istanbul/node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.17",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
- "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
- "dev": true,
- "dependencies": {
- "@jridgewell/resolve-uri": "3.1.0",
- "@jridgewell/sourcemap-codec": "1.4.14"
- }
- },
"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",
@@ -3925,16 +4030,16 @@
"dev": true
},
"node_modules/write-file-atomic": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.0.tgz",
- "integrity": "sha512-R7NYMnHSlV42K54lwY9lvW6MnSm1HSJqZL3xiSgi9E7//FYaI74r2G0rd+/X6VAMkHEdzxQaU5HUOXWUz5kA/w==",
+ "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": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
}
},
"node_modules/y18n": {
@@ -3953,9 +4058,9 @@
"dev": true
},
"node_modules/yargs": {
- "version": "17.6.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz",
- "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==",
+ "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",
@@ -4000,2993 +4105,5 @@
"url": "https://github.com/sponsors/sindresorhus"
}
}
- },
- "dependencies": {
- "@ampproject/remapping": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
- "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==",
- "dev": true,
- "requires": {
- "@jridgewell/gen-mapping": "^0.1.0",
- "@jridgewell/trace-mapping": "^0.3.9"
- }
- },
- "@aws-cdk/asset-awscli-v1": {
- "version": "2.2.52",
- "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.52.tgz",
- "integrity": "sha512-9dBPrvByWrUOcs5Rjwv08FWSummo1Uk/EgE3dCFDqvIqlSTudEmu6TGU3zrs00rfcAjqDv6gBuSttzG5f9tfdQ=="
- },
- "@aws-cdk/asset-kubectl-v20": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@aws-cdk/asset-kubectl-v20/-/asset-kubectl-v20-2.1.1.tgz",
- "integrity": "sha512-U1ntiX8XiMRRRH5J1IdC+1t5CE89015cwyt5U63Cpk0GnMlN5+h9WsWMlKlPXZR4rdq/m806JRlBMRpBUB2Dhw=="
- },
- "@aws-cdk/asset-node-proxy-agent-v5": {
- "version": "2.0.42",
- "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v5/-/asset-node-proxy-agent-v5-2.0.42.tgz",
- "integrity": "sha512-PxvP1UU2xa4k3Ea78DxAYY8ADvwWZ/nPu+xsjQLsT+MP+aB3RZ3pGc/fNlH7Rg56Zyb/j3GSdihAy4Oi5xa+TQ=="
- },
- "@babel/code-frame": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
- "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==",
- "dev": true,
- "requires": {
- "@babel/highlight": "^7.18.6"
- }
- },
- "@babel/compat-data": {
- "version": "7.20.10",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.10.tgz",
- "integrity": "sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg==",
- "dev": true
- },
- "@babel/core": {
- "version": "7.20.12",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz",
- "integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==",
- "dev": true,
- "requires": {
- "@ampproject/remapping": "^2.1.0",
- "@babel/code-frame": "^7.18.6",
- "@babel/generator": "^7.20.7",
- "@babel/helper-compilation-targets": "^7.20.7",
- "@babel/helper-module-transforms": "^7.20.11",
- "@babel/helpers": "^7.20.7",
- "@babel/parser": "^7.20.7",
- "@babel/template": "^7.20.7",
- "@babel/traverse": "^7.20.12",
- "@babel/types": "^7.20.7",
- "convert-source-map": "^1.7.0",
- "debug": "^4.1.0",
- "gensync": "^1.0.0-beta.2",
- "json5": "^2.2.2",
- "semver": "^6.3.0"
- },
- "dependencies": {
- "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
- }
- }
- },
- "@babel/generator": {
- "version": "7.20.7",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.7.tgz",
- "integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.20.7",
- "@jridgewell/gen-mapping": "^0.3.2",
- "jsesc": "^2.5.1"
- },
- "dependencies": {
- "@jridgewell/gen-mapping": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
- "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
- "dev": true,
- "requires": {
- "@jridgewell/set-array": "^1.0.1",
- "@jridgewell/sourcemap-codec": "^1.4.10",
- "@jridgewell/trace-mapping": "^0.3.9"
- }
- }
- }
- },
- "@babel/helper-compilation-targets": {
- "version": "7.20.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz",
- "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==",
- "dev": true,
- "requires": {
- "@babel/compat-data": "^7.20.5",
- "@babel/helper-validator-option": "^7.18.6",
- "browserslist": "^4.21.3",
- "lru-cache": "^5.1.1",
- "semver": "^6.3.0"
- }
- },
- "@babel/helper-environment-visitor": {
- "version": "7.18.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz",
- "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==",
- "dev": true
- },
- "@babel/helper-function-name": {
- "version": "7.19.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz",
- "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==",
- "dev": true,
- "requires": {
- "@babel/template": "^7.18.10",
- "@babel/types": "^7.19.0"
- }
- },
- "@babel/helper-hoist-variables": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz",
- "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.18.6"
- }
- },
- "@babel/helper-module-imports": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz",
- "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.18.6"
- }
- },
- "@babel/helper-module-transforms": {
- "version": "7.20.11",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz",
- "integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==",
- "dev": true,
- "requires": {
- "@babel/helper-environment-visitor": "^7.18.9",
- "@babel/helper-module-imports": "^7.18.6",
- "@babel/helper-simple-access": "^7.20.2",
- "@babel/helper-split-export-declaration": "^7.18.6",
- "@babel/helper-validator-identifier": "^7.19.1",
- "@babel/template": "^7.20.7",
- "@babel/traverse": "^7.20.10",
- "@babel/types": "^7.20.7"
- }
- },
- "@babel/helper-plugin-utils": {
- "version": "7.20.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz",
- "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==",
- "dev": true
- },
- "@babel/helper-simple-access": {
- "version": "7.20.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz",
- "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.20.2"
- }
- },
- "@babel/helper-split-export-declaration": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz",
- "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.18.6"
- }
- },
- "@babel/helper-string-parser": {
- "version": "7.19.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz",
- "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==",
- "dev": true
- },
- "@babel/helper-validator-identifier": {
- "version": "7.19.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
- "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
- "dev": true
- },
- "@babel/helper-validator-option": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz",
- "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==",
- "dev": true
- },
- "@babel/helpers": {
- "version": "7.20.13",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.13.tgz",
- "integrity": "sha512-nzJ0DWCL3gB5RCXbUO3KIMMsBY2Eqbx8mBpKGE/02PgyRQFcPQLbkQ1vyy596mZLaP+dAfD+R4ckASzNVmW3jg==",
- "dev": true,
- "requires": {
- "@babel/template": "^7.20.7",
- "@babel/traverse": "^7.20.13",
- "@babel/types": "^7.20.7"
- }
- },
- "@babel/highlight": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
- "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
- "dev": true,
- "requires": {
- "@babel/helper-validator-identifier": "^7.18.6",
- "chalk": "^2.0.0",
- "js-tokens": "^4.0.0"
- },
- "dependencies": {
- "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,
- "requires": {
- "color-convert": "^1.9.0"
- }
- },
- "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,
- "requires": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- }
- },
- "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,
- "requires": {
- "color-name": "1.1.3"
- }
- },
- "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
- },
- "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
- },
- "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
- },
- "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,
- "requires": {
- "has-flag": "^3.0.0"
- }
- }
- }
- },
- "@babel/parser": {
- "version": "7.20.13",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.13.tgz",
- "integrity": "sha512-gFDLKMfpiXCsjt4za2JA9oTMn70CeseCehb11kRZgvd7+F67Hih3OHOK24cRrWECJ/ljfPGac6ygXAs/C8kIvw==",
- "dev": true
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.12.13"
- }
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@babel/plugin-syntax-jsx": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz",
- "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.18.6"
- }
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.14.5"
- }
- },
- "@babel/plugin-syntax-typescript": {
- "version": "7.20.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz",
- "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.19.0"
- }
- },
- "@babel/template": {
- "version": "7.20.7",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz",
- "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.18.6",
- "@babel/parser": "^7.20.7",
- "@babel/types": "^7.20.7"
- }
- },
- "@babel/traverse": {
- "version": "7.20.13",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.13.tgz",
- "integrity": "sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ==",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.18.6",
- "@babel/generator": "^7.20.7",
- "@babel/helper-environment-visitor": "^7.18.9",
- "@babel/helper-function-name": "^7.19.0",
- "@babel/helper-hoist-variables": "^7.18.6",
- "@babel/helper-split-export-declaration": "^7.18.6",
- "@babel/parser": "^7.20.13",
- "@babel/types": "^7.20.7",
- "debug": "^4.1.0",
- "globals": "^11.1.0"
- }
- },
- "@babel/types": {
- "version": "7.20.7",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz",
- "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==",
- "dev": true,
- "requires": {
- "@babel/helper-string-parser": "^7.19.4",
- "@babel/helper-validator-identifier": "^7.19.1",
- "to-fast-properties": "^2.0.0"
- }
- },
- "@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
- },
- "@cspotcode/source-map-support": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
- "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
- "dev": true,
- "requires": {
- "@jridgewell/trace-mapping": "0.3.9"
- }
- },
- "@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,
- "requires": {
- "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"
- }
- },
- "@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
- },
- "@jest/console": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.4.1.tgz",
- "integrity": "sha512-m+XpwKSi3PPM9znm5NGS8bBReeAJJpSkL1OuFCqaMaJL2YX9YXLkkI+MBchMPwu+ZuM2rynL51sgfkQteQ1CKQ==",
- "dev": true,
- "requires": {
- "@jest/types": "^29.4.1",
- "@types/node": "*",
- "chalk": "^4.0.0",
- "jest-message-util": "^29.4.1",
- "jest-util": "^29.4.1",
- "slash": "^3.0.0"
- }
- },
- "@jest/core": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.4.1.tgz",
- "integrity": "sha512-RXFTohpBqpaTebNdg5l3I5yadnKo9zLBajMT0I38D0tDhreVBYv3fA8kywthI00sWxPztWLD3yjiUkewwu/wKA==",
- "dev": true,
- "requires": {
- "@jest/console": "^29.4.1",
- "@jest/reporters": "^29.4.1",
- "@jest/test-result": "^29.4.1",
- "@jest/transform": "^29.4.1",
- "@jest/types": "^29.4.1",
- "@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.4.0",
- "jest-config": "^29.4.1",
- "jest-haste-map": "^29.4.1",
- "jest-message-util": "^29.4.1",
- "jest-regex-util": "^29.2.0",
- "jest-resolve": "^29.4.1",
- "jest-resolve-dependencies": "^29.4.1",
- "jest-runner": "^29.4.1",
- "jest-runtime": "^29.4.1",
- "jest-snapshot": "^29.4.1",
- "jest-util": "^29.4.1",
- "jest-validate": "^29.4.1",
- "jest-watcher": "^29.4.1",
- "micromatch": "^4.0.4",
- "pretty-format": "^29.4.1",
- "slash": "^3.0.0",
- "strip-ansi": "^6.0.0"
- }
- },
- "@jest/environment": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.4.1.tgz",
- "integrity": "sha512-pJ14dHGSQke7Q3mkL/UZR9ZtTOxqskZaC91NzamEH4dlKRt42W+maRBXiw/LWkdJe+P0f/zDR37+SPMplMRlPg==",
- "dev": true,
- "requires": {
- "@jest/fake-timers": "^29.4.1",
- "@jest/types": "^29.4.1",
- "@types/node": "*",
- "jest-mock": "^29.4.1"
- }
- },
- "@jest/expect": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.4.1.tgz",
- "integrity": "sha512-ZxKJP5DTUNF2XkpJeZIzvnzF1KkfrhEF6Rz0HGG69fHl6Bgx5/GoU3XyaeFYEjuuKSOOsbqD/k72wFvFxc3iTw==",
- "dev": true,
- "requires": {
- "expect": "^29.4.1",
- "jest-snapshot": "^29.4.1"
- }
- },
- "@jest/expect-utils": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.4.1.tgz",
- "integrity": "sha512-w6YJMn5DlzmxjO00i9wu2YSozUYRBhIoJ6nQwpMYcBMtiqMGJm1QBzOf6DDgRao8dbtpDoaqLg6iiQTvv0UHhQ==",
- "dev": true,
- "requires": {
- "jest-get-type": "^29.2.0"
- }
- },
- "@jest/fake-timers": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.4.1.tgz",
- "integrity": "sha512-/1joI6rfHFmmm39JxNfmNAO3Nwm6Y0VoL5fJDy7H1AtWrD1CgRtqJbN9Ld6rhAkGO76qqp4cwhhxJ9o9kYjQMw==",
- "dev": true,
- "requires": {
- "@jest/types": "^29.4.1",
- "@sinonjs/fake-timers": "^10.0.2",
- "@types/node": "*",
- "jest-message-util": "^29.4.1",
- "jest-mock": "^29.4.1",
- "jest-util": "^29.4.1"
- }
- },
- "@jest/globals": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.4.1.tgz",
- "integrity": "sha512-znoK2EuFytbHH0ZSf2mQK2K1xtIgmaw4Da21R2C/NE/+NnItm5mPEFQmn8gmF3f0rfOlmZ3Y3bIf7bFj7DHxAA==",
- "dev": true,
- "requires": {
- "@jest/environment": "^29.4.1",
- "@jest/expect": "^29.4.1",
- "@jest/types": "^29.4.1",
- "jest-mock": "^29.4.1"
- }
- },
- "@jest/reporters": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.4.1.tgz",
- "integrity": "sha512-AISY5xpt2Xpxj9R6y0RF1+O6GRy9JsGa8+vK23Lmzdy1AYcpQn5ItX79wJSsTmfzPKSAcsY1LNt/8Y5Xe5LOSg==",
- "dev": true,
- "requires": {
- "@bcoe/v8-coverage": "^0.2.3",
- "@jest/console": "^29.4.1",
- "@jest/test-result": "^29.4.1",
- "@jest/transform": "^29.4.1",
- "@jest/types": "^29.4.1",
- "@jridgewell/trace-mapping": "^0.3.15",
- "@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": "^5.1.0",
- "istanbul-lib-report": "^3.0.0",
- "istanbul-lib-source-maps": "^4.0.0",
- "istanbul-reports": "^3.1.3",
- "jest-message-util": "^29.4.1",
- "jest-util": "^29.4.1",
- "jest-worker": "^29.4.1",
- "slash": "^3.0.0",
- "string-length": "^4.0.1",
- "strip-ansi": "^6.0.0",
- "v8-to-istanbul": "^9.0.1"
- },
- "dependencies": {
- "@jridgewell/trace-mapping": {
- "version": "0.3.17",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
- "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
- "dev": true,
- "requires": {
- "@jridgewell/resolve-uri": "3.1.0",
- "@jridgewell/sourcemap-codec": "1.4.14"
- }
- }
- }
- },
- "@jest/schemas": {
- "version": "29.4.0",
- "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.0.tgz",
- "integrity": "sha512-0E01f/gOZeNTG76i5eWWSupvSHaIINrTie7vCyjiYFKgzNdyEGd12BUv4oNBFHOqlHDbtoJi3HrQ38KCC90NsQ==",
- "dev": true,
- "requires": {
- "@sinclair/typebox": "^0.25.16"
- }
- },
- "@jest/source-map": {
- "version": "29.2.0",
- "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.2.0.tgz",
- "integrity": "sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ==",
- "dev": true,
- "requires": {
- "@jridgewell/trace-mapping": "^0.3.15",
- "callsites": "^3.0.0",
- "graceful-fs": "^4.2.9"
- },
- "dependencies": {
- "@jridgewell/trace-mapping": {
- "version": "0.3.17",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
- "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
- "dev": true,
- "requires": {
- "@jridgewell/resolve-uri": "3.1.0",
- "@jridgewell/sourcemap-codec": "1.4.14"
- }
- }
- }
- },
- "@jest/test-result": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.4.1.tgz",
- "integrity": "sha512-WRt29Lwt+hEgfN8QDrXqXGgCTidq1rLyFqmZ4lmJOpVArC8daXrZWkWjiaijQvgd3aOUj2fM8INclKHsQW9YyQ==",
- "dev": true,
- "requires": {
- "@jest/console": "^29.4.1",
- "@jest/types": "^29.4.1",
- "@types/istanbul-lib-coverage": "^2.0.0",
- "collect-v8-coverage": "^1.0.0"
- }
- },
- "@jest/test-sequencer": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.4.1.tgz",
- "integrity": "sha512-v5qLBNSsM0eHzWLXsQ5fiB65xi49A3ILPSFQKPXzGL4Vyux0DPZAIN7NAFJa9b4BiTDP9MBF/Zqc/QA1vuiJ0w==",
- "dev": true,
- "requires": {
- "@jest/test-result": "^29.4.1",
- "graceful-fs": "^4.2.9",
- "jest-haste-map": "^29.4.1",
- "slash": "^3.0.0"
- }
- },
- "@jest/transform": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.4.1.tgz",
- "integrity": "sha512-5w6YJrVAtiAgr0phzKjYd83UPbCXsBRTeYI4BXokv9Er9CcrH9hfXL/crCvP2d2nGOcovPUnlYiLPFLZrkG5Hg==",
- "dev": true,
- "requires": {
- "@babel/core": "^7.11.6",
- "@jest/types": "^29.4.1",
- "@jridgewell/trace-mapping": "^0.3.15",
- "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.4.1",
- "jest-regex-util": "^29.2.0",
- "jest-util": "^29.4.1",
- "micromatch": "^4.0.4",
- "pirates": "^4.0.4",
- "slash": "^3.0.0",
- "write-file-atomic": "^5.0.0"
- },
- "dependencies": {
- "@jridgewell/trace-mapping": {
- "version": "0.3.17",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
- "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
- "dev": true,
- "requires": {
- "@jridgewell/resolve-uri": "3.1.0",
- "@jridgewell/sourcemap-codec": "1.4.14"
- }
- }
- }
- },
- "@jest/types": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.4.1.tgz",
- "integrity": "sha512-zbrAXDUOnpJ+FMST2rV7QZOgec8rskg2zv8g2ajeqitp4tvZiyqTCYXANrKsM+ryj5o+LI+ZN2EgU9drrkiwSA==",
- "dev": true,
- "requires": {
- "@jest/schemas": "^29.4.0",
- "@types/istanbul-lib-coverage": "^2.0.0",
- "@types/istanbul-reports": "^3.0.0",
- "@types/node": "*",
- "@types/yargs": "^17.0.8",
- "chalk": "^4.0.0"
- }
- },
- "@jridgewell/gen-mapping": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
- "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==",
- "dev": true,
- "requires": {
- "@jridgewell/set-array": "^1.0.0",
- "@jridgewell/sourcemap-codec": "^1.4.10"
- }
- },
- "@jridgewell/resolve-uri": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
- "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
- "dev": true
- },
- "@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
- },
- "@jridgewell/sourcemap-codec": {
- "version": "1.4.14",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
- "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
- "dev": true
- },
- "@jridgewell/trace-mapping": {
- "version": "0.3.9",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
- "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
- "dev": true,
- "requires": {
- "@jridgewell/resolve-uri": "^3.0.3",
- "@jridgewell/sourcemap-codec": "^1.4.10"
- }
- },
- "@sinclair/typebox": {
- "version": "0.25.21",
- "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.21.tgz",
- "integrity": "sha512-gFukHN4t8K4+wVC+ECqeqwzBDeFeTzBXroBTqE6vcWrQGbEUpHO7LYdG0f4xnvYq4VOEwITSlHlp0JBAIFMS/g==",
- "dev": true
- },
- "@sinonjs/commons": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz",
- "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==",
- "dev": true,
- "requires": {
- "type-detect": "4.0.8"
- }
- },
- "@sinonjs/fake-timers": {
- "version": "10.0.2",
- "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz",
- "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==",
- "dev": true,
- "requires": {
- "@sinonjs/commons": "^2.0.0"
- }
- },
- "@tsconfig/node10": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
- "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==",
- "dev": true
- },
- "@tsconfig/node12": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
- "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
- "dev": true
- },
- "@tsconfig/node14": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
- "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
- "dev": true
- },
- "@tsconfig/node16": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
- "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
- "dev": true
- },
- "@types/adm-zip": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.5.0.tgz",
- "integrity": "sha512-FCJBJq9ODsQZUNURo5ILAQueuA8WJhRvuihS3ke2iI25mJlfV2LK8jG2Qj2z2AWg8U0FtWWqBHVRetceLskSaw==",
- "dev": true,
- "requires": {
- "@types/node": "*"
- }
- },
- "@types/babel__core": {
- "version": "7.20.0",
- "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz",
- "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==",
- "dev": true,
- "requires": {
- "@babel/parser": "^7.20.7",
- "@babel/types": "^7.20.7",
- "@types/babel__generator": "*",
- "@types/babel__template": "*",
- "@types/babel__traverse": "*"
- }
- },
- "@types/babel__generator": {
- "version": "7.6.4",
- "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz",
- "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.0.0"
- }
- },
- "@types/babel__template": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz",
- "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==",
- "dev": true,
- "requires": {
- "@babel/parser": "^7.1.0",
- "@babel/types": "^7.0.0"
- }
- },
- "@types/babel__traverse": {
- "version": "7.18.3",
- "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz",
- "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.3.0"
- }
- },
- "@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,
- "requires": {
- "@types/node": "*"
- }
- },
- "@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
- },
- "@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,
- "requires": {
- "@types/istanbul-lib-coverage": "*"
- }
- },
- "@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,
- "requires": {
- "@types/istanbul-lib-report": "*"
- }
- },
- "@types/jest": {
- "version": "29.4.0",
- "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.4.0.tgz",
- "integrity": "sha512-VaywcGQ9tPorCX/Jkkni7RWGFfI11whqzs8dvxF41P17Z+z872thvEvlIbznjPJ02kl1HMX3LmLOonsj2n7HeQ==",
- "dev": true,
- "requires": {
- "expect": "^29.0.0",
- "pretty-format": "^29.0.0"
- }
- },
- "@types/node": {
- "version": "18.11.18",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz",
- "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==",
- "dev": true
- },
- "@types/prettier": {
- "version": "2.7.2",
- "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz",
- "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==",
- "dev": true
- },
- "@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
- },
- "@types/yargs": {
- "version": "17.0.20",
- "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.20.tgz",
- "integrity": "sha512-eknWrTHofQuPk2iuqDm1waA7V6xPlbgBoaaXEgYkClhLOnB0TtbW+srJaOToAgawPxPlHQzwypFA2bhZaUGP5A==",
- "dev": true,
- "requires": {
- "@types/yargs-parser": "*"
- }
- },
- "@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
- },
- "acorn": {
- "version": "8.8.2",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
- "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==",
- "dev": true
- },
- "acorn-walk": {
- "version": "8.2.0",
- "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
- "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
- "dev": true
- },
- "adm-zip": {
- "version": "0.5.10",
- "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.10.tgz",
- "integrity": "sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ=="
- },
- "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,
- "requires": {
- "type-fest": "^0.21.3"
- }
- },
- "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
- },
- "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,
- "requires": {
- "color-convert": "^2.0.1"
- }
- },
- "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,
- "requires": {
- "normalize-path": "^3.0.0",
- "picomatch": "^2.0.4"
- }
- },
- "arg": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
- "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
- "dev": true
- },
- "argparse": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
- "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
- "dev": true,
- "requires": {
- "sprintf-js": "~1.0.2"
- }
- },
- "aws-cdk-lib": {
- "version": "2.63.0",
- "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.63.0.tgz",
- "integrity": "sha512-+thToi/7coSufwaEafgofTaZERXxFUeEwEIp0SGU0wHz6IbPll5yAzoEIkE51kM8AMCMfqwJddYOjM3qs43cPg==",
- "requires": {
- "@aws-cdk/asset-awscli-v1": "^2.2.52",
- "@aws-cdk/asset-kubectl-v20": "^2.1.1",
- "@aws-cdk/asset-node-proxy-agent-v5": "^2.0.42",
- "@balena/dockerignore": "^1.0.2",
- "case": "1.6.3",
- "fs-extra": "^9.1.0",
- "ignore": "^5.2.4",
- "jsonschema": "^1.4.1",
- "minimatch": "^3.1.2",
- "punycode": "^2.3.0",
- "semver": "^7.3.8",
- "yaml": "1.10.2"
- },
- "dependencies": {
- "@balena/dockerignore": {
- "version": "1.0.2",
- "bundled": true
- },
- "at-least-node": {
- "version": "1.0.0",
- "bundled": true
- },
- "balanced-match": {
- "version": "1.0.2",
- "bundled": true
- },
- "brace-expansion": {
- "version": "1.1.11",
- "bundled": true,
- "requires": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "case": {
- "version": "1.6.3",
- "bundled": true
- },
- "concat-map": {
- "version": "0.0.1",
- "bundled": true
- },
- "fs-extra": {
- "version": "9.1.0",
- "bundled": true,
- "requires": {
- "at-least-node": "^1.0.0",
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- }
- },
- "graceful-fs": {
- "version": "4.2.10",
- "bundled": true
- },
- "ignore": {
- "version": "5.2.4",
- "bundled": true
- },
- "jsonfile": {
- "version": "6.1.0",
- "bundled": true,
- "requires": {
- "graceful-fs": "^4.1.6",
- "universalify": "^2.0.0"
- }
- },
- "jsonschema": {
- "version": "1.4.1",
- "bundled": true
- },
- "lru-cache": {
- "version": "6.0.0",
- "bundled": true,
- "requires": {
- "yallist": "^4.0.0"
- }
- },
- "minimatch": {
- "version": "3.1.2",
- "bundled": true,
- "requires": {
- "brace-expansion": "^1.1.7"
- }
- },
- "punycode": {
- "version": "2.3.0",
- "bundled": true
- },
- "semver": {
- "version": "7.3.8",
- "bundled": true,
- "requires": {
- "lru-cache": "^6.0.0"
- }
- },
- "universalify": {
- "version": "2.0.0",
- "bundled": true
- },
- "yallist": {
- "version": "4.0.0",
- "bundled": true
- },
- "yaml": {
- "version": "1.10.2",
- "bundled": true
- }
- }
- },
- "babel-jest": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.4.1.tgz",
- "integrity": "sha512-xBZa/pLSsF/1sNpkgsiT3CmY7zV1kAsZ9OxxtrFqYucnOuRftXAfcJqcDVyOPeN4lttWTwhLdu0T9f8uvoPEUg==",
- "dev": true,
- "requires": {
- "@jest/transform": "^29.4.1",
- "@types/babel__core": "^7.1.14",
- "babel-plugin-istanbul": "^6.1.1",
- "babel-preset-jest": "^29.4.0",
- "chalk": "^4.0.0",
- "graceful-fs": "^4.2.9",
- "slash": "^3.0.0"
- }
- },
- "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,
- "requires": {
- "@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"
- }
- },
- "babel-plugin-jest-hoist": {
- "version": "29.4.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.4.0.tgz",
- "integrity": "sha512-a/sZRLQJEmsmejQ2rPEUe35nO1+C9dc9O1gplH1SXmJxveQSRUYdBk8yGZG/VOUuZs1u2aHZJusEGoRMbhhwCg==",
- "dev": true,
- "requires": {
- "@babel/template": "^7.3.3",
- "@babel/types": "^7.3.3",
- "@types/babel__core": "^7.1.14",
- "@types/babel__traverse": "^7.0.6"
- }
- },
- "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,
- "requires": {
- "@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"
- }
- },
- "babel-preset-jest": {
- "version": "29.4.0",
- "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.4.0.tgz",
- "integrity": "sha512-fUB9vZflUSM3dO/6M2TCAepTzvA4VkOvl67PjErcrQMGt9Eve7uazaeyCZ2th3UtI7ljpiBJES0F7A1vBRsLZA==",
- "dev": true,
- "requires": {
- "babel-plugin-jest-hoist": "^29.4.0",
- "babel-preset-current-node-syntax": "^1.0.0"
- }
- },
- "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
- },
- "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,
- "requires": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
- "dev": true,
- "requires": {
- "fill-range": "^7.0.1"
- }
- },
- "browserslist": {
- "version": "4.21.4",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
- "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==",
- "dev": true,
- "requires": {
- "caniuse-lite": "^1.0.30001400",
- "electron-to-chromium": "^1.4.251",
- "node-releases": "^2.0.6",
- "update-browserslist-db": "^1.0.9"
- }
- },
- "bs-logger": {
- "version": "0.2.6",
- "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz",
- "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==",
- "dev": true,
- "requires": {
- "fast-json-stable-stringify": "2.x"
- }
- },
- "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,
- "requires": {
- "node-int64": "^0.4.0"
- }
- },
- "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
- },
- "callsites": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
- "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
- "dev": true
- },
- "camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
- "dev": true
- },
- "caniuse-lite": {
- "version": "1.0.30001449",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001449.tgz",
- "integrity": "sha512-CPB+UL9XMT/Av+pJxCKGhdx+yg1hzplvFJQlJ2n68PyQGMz9L/E2zCyLdOL8uasbouTUgnPl+y0tccI/se+BEw==",
- "dev": true
- },
- "chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
- "requires": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- }
- },
- "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
- },
- "ci-info": {
- "version": "3.7.1",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.1.tgz",
- "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==",
- "dev": true
- },
- "cjs-module-lexer": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz",
- "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==",
- "dev": true
- },
- "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,
- "requires": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.1",
- "wrap-ansi": "^7.0.0"
- }
- },
- "co": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
- "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
- "dev": true
- },
- "collect-v8-coverage": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz",
- "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==",
- "dev": true
- },
- "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,
- "requires": {
- "color-name": "~1.1.4"
- }
- },
- "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
- },
- "concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "dev": true
- },
- "constructs": {
- "version": "10.1.236",
- "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.1.236.tgz",
- "integrity": "sha512-JBikdlmN5sKDjwZmPPoveNr7K6N7SQLBEJY83r3Px86CGyMu0YXtaYpjFg2fQd9zs8X77QnyNzb54SKiicSD9g==",
- "peer": true
- },
- "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
- },
- "create-require": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
- "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
- "dev": true
- },
- "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,
- "requires": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
- }
- },
- "debug": {
- "version": "4.3.4",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
- "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
- "dev": true,
- "requires": {
- "ms": "2.1.2"
- }
- },
- "dedent": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
- "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==",
- "dev": true
- },
- "deepmerge": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
- "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
- "dev": true
- },
- "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
- },
- "diff": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
- "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
- "dev": true
- },
- "diff-sequences": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.3.1.tgz",
- "integrity": "sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==",
- "dev": true
- },
- "electron-to-chromium": {
- "version": "1.4.284",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz",
- "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==",
- "dev": true
- },
- "emittery": {
- "version": "0.13.1",
- "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
- "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==",
- "dev": true
- },
- "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
- },
- "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,
- "requires": {
- "is-arrayish": "^0.2.1"
- }
- },
- "escalade": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
- "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
- "dev": true
- },
- "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
- },
- "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
- },
- "execa": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
- "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
- "dev": true,
- "requires": {
- "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"
- }
- },
- "exit": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
- "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==",
- "dev": true
- },
- "expect": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/expect/-/expect-29.4.1.tgz",
- "integrity": "sha512-OKrGESHOaMxK3b6zxIq9SOW8kEXztKff/Dvg88j4xIJxur1hspEbedVkR3GpHe5LO+WB2Qw7OWN0RMTdp6as5A==",
- "dev": true,
- "requires": {
- "@jest/expect-utils": "^29.4.1",
- "jest-get-type": "^29.2.0",
- "jest-matcher-utils": "^29.4.1",
- "jest-message-util": "^29.4.1",
- "jest-util": "^29.4.1"
- }
- },
- "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
- },
- "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,
- "requires": {
- "bser": "2.1.1"
- }
- },
- "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,
- "requires": {
- "to-regex-range": "^5.0.1"
- }
- },
- "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,
- "requires": {
- "locate-path": "^5.0.0",
- "path-exists": "^4.0.0"
- }
- },
- "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
- },
- "fsevents": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
- "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
- "dev": true,
- "optional": true
- },
- "function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
- "dev": true
- },
- "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
- },
- "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
- },
- "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
- },
- "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
- },
- "glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "dev": true,
- "requires": {
- "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"
- }
- },
- "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
- },
- "graceful-fs": {
- "version": "4.2.10",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
- "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
- "dev": true
- },
- "has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "dev": true,
- "requires": {
- "function-bind": "^1.1.1"
- }
- },
- "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
- },
- "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
- },
- "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
- },
- "import-local": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
- "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
- "dev": true,
- "requires": {
- "pkg-dir": "^4.2.0",
- "resolve-cwd": "^3.0.0"
- }
- },
- "imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
- "dev": true
- },
- "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,
- "requires": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "dev": true
- },
- "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
- },
- "is-core-module": {
- "version": "2.11.0",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
- "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
- "dev": true,
- "requires": {
- "has": "^1.0.3"
- }
- },
- "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
- },
- "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
- },
- "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
- },
- "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
- },
- "isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true
- },
- "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
- },
- "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,
- "requires": {
- "@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"
- }
- },
- "istanbul-lib-report": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
- "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==",
- "dev": true,
- "requires": {
- "istanbul-lib-coverage": "^3.0.0",
- "make-dir": "^3.0.0",
- "supports-color": "^7.1.0"
- }
- },
- "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,
- "requires": {
- "debug": "^4.1.1",
- "istanbul-lib-coverage": "^3.0.0",
- "source-map": "^0.6.1"
- }
- },
- "istanbul-reports": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz",
- "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==",
- "dev": true,
- "requires": {
- "html-escaper": "^2.0.0",
- "istanbul-lib-report": "^3.0.0"
- }
- },
- "jest": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest/-/jest-29.4.1.tgz",
- "integrity": "sha512-cknimw7gAXPDOmj0QqztlxVtBVCw2lYY9CeIE5N6kD+kET1H4H79HSNISJmijb1HF+qk+G+ploJgiDi5k/fRlg==",
- "dev": true,
- "requires": {
- "@jest/core": "^29.4.1",
- "@jest/types": "^29.4.1",
- "import-local": "^3.0.2",
- "jest-cli": "^29.4.1"
- }
- },
- "jest-changed-files": {
- "version": "29.4.0",
- "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.4.0.tgz",
- "integrity": "sha512-rnI1oPxgFghoz32Y8eZsGJMjW54UlqT17ycQeCEktcxxwqqKdlj9afl8LNeO0Pbu+h2JQHThQP0BzS67eTRx4w==",
- "dev": true,
- "requires": {
- "execa": "^5.0.0",
- "p-limit": "^3.1.0"
- }
- },
- "jest-circus": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.4.1.tgz",
- "integrity": "sha512-v02NuL5crMNY4CGPHBEflLzl4v91NFb85a+dH9a1pUNx6Xjggrd8l9pPy4LZ1VYNRXlb+f65+7O/MSIbLir6pA==",
- "dev": true,
- "requires": {
- "@jest/environment": "^29.4.1",
- "@jest/expect": "^29.4.1",
- "@jest/test-result": "^29.4.1",
- "@jest/types": "^29.4.1",
- "@types/node": "*",
- "chalk": "^4.0.0",
- "co": "^4.6.0",
- "dedent": "^0.7.0",
- "is-generator-fn": "^2.0.0",
- "jest-each": "^29.4.1",
- "jest-matcher-utils": "^29.4.1",
- "jest-message-util": "^29.4.1",
- "jest-runtime": "^29.4.1",
- "jest-snapshot": "^29.4.1",
- "jest-util": "^29.4.1",
- "p-limit": "^3.1.0",
- "pretty-format": "^29.4.1",
- "slash": "^3.0.0",
- "stack-utils": "^2.0.3"
- }
- },
- "jest-cli": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.4.1.tgz",
- "integrity": "sha512-jz7GDIhtxQ37M+9dlbv5K+/FVcIo1O/b1sX3cJgzlQUf/3VG25nvuWzlDC4F1FLLzUThJeWLu8I7JF9eWpuURQ==",
- "dev": true,
- "requires": {
- "@jest/core": "^29.4.1",
- "@jest/test-result": "^29.4.1",
- "@jest/types": "^29.4.1",
- "chalk": "^4.0.0",
- "exit": "^0.1.2",
- "graceful-fs": "^4.2.9",
- "import-local": "^3.0.2",
- "jest-config": "^29.4.1",
- "jest-util": "^29.4.1",
- "jest-validate": "^29.4.1",
- "prompts": "^2.0.1",
- "yargs": "^17.3.1"
- }
- },
- "jest-config": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.4.1.tgz",
- "integrity": "sha512-g7p3q4NuXiM4hrS4XFATTkd+2z0Ml2RhFmFPM8c3WyKwVDNszbl4E7cV7WIx1YZeqqCtqbtTtZhGZWJlJqngzg==",
- "dev": true,
- "requires": {
- "@babel/core": "^7.11.6",
- "@jest/test-sequencer": "^29.4.1",
- "@jest/types": "^29.4.1",
- "babel-jest": "^29.4.1",
- "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.4.1",
- "jest-environment-node": "^29.4.1",
- "jest-get-type": "^29.2.0",
- "jest-regex-util": "^29.2.0",
- "jest-resolve": "^29.4.1",
- "jest-runner": "^29.4.1",
- "jest-util": "^29.4.1",
- "jest-validate": "^29.4.1",
- "micromatch": "^4.0.4",
- "parse-json": "^5.2.0",
- "pretty-format": "^29.4.1",
- "slash": "^3.0.0",
- "strip-json-comments": "^3.1.1"
- }
- },
- "jest-diff": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.4.1.tgz",
- "integrity": "sha512-uazdl2g331iY56CEyfbNA0Ut7Mn2ulAG5vUaEHXycf1L6IPyuImIxSz4F0VYBKi7LYIuxOwTZzK3wh5jHzASMw==",
- "dev": true,
- "requires": {
- "chalk": "^4.0.0",
- "diff-sequences": "^29.3.1",
- "jest-get-type": "^29.2.0",
- "pretty-format": "^29.4.1"
- }
- },
- "jest-docblock": {
- "version": "29.2.0",
- "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.2.0.tgz",
- "integrity": "sha512-bkxUsxTgWQGbXV5IENmfiIuqZhJcyvF7tU4zJ/7ioTutdz4ToB5Yx6JOFBpgI+TphRY4lhOyCWGNH/QFQh5T6A==",
- "dev": true,
- "requires": {
- "detect-newline": "^3.0.0"
- }
- },
- "jest-each": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.4.1.tgz",
- "integrity": "sha512-QlYFiX3llJMWUV0BtWht/esGEz9w+0i7BHwODKCze7YzZzizgExB9MOfiivF/vVT0GSQ8wXLhvHXh3x2fVD4QQ==",
- "dev": true,
- "requires": {
- "@jest/types": "^29.4.1",
- "chalk": "^4.0.0",
- "jest-get-type": "^29.2.0",
- "jest-util": "^29.4.1",
- "pretty-format": "^29.4.1"
- }
- },
- "jest-environment-node": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.4.1.tgz",
- "integrity": "sha512-x/H2kdVgxSkxWAIlIh9MfMuBa0hZySmfsC5lCsWmWr6tZySP44ediRKDUiNggX/eHLH7Cd5ZN10Rw+XF5tXsqg==",
- "dev": true,
- "requires": {
- "@jest/environment": "^29.4.1",
- "@jest/fake-timers": "^29.4.1",
- "@jest/types": "^29.4.1",
- "@types/node": "*",
- "jest-mock": "^29.4.1",
- "jest-util": "^29.4.1"
- }
- },
- "jest-get-type": {
- "version": "29.2.0",
- "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.2.0.tgz",
- "integrity": "sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==",
- "dev": true
- },
- "jest-haste-map": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.4.1.tgz",
- "integrity": "sha512-imTjcgfVVTvg02khXL11NNLTx9ZaofbAWhilrMg/G8dIkp+HYCswhxf0xxJwBkfhWb3e8dwbjuWburvxmcr58w==",
- "dev": true,
- "requires": {
- "@jest/types": "^29.4.1",
- "@types/graceful-fs": "^4.1.3",
- "@types/node": "*",
- "anymatch": "^3.0.3",
- "fb-watchman": "^2.0.0",
- "fsevents": "^2.3.2",
- "graceful-fs": "^4.2.9",
- "jest-regex-util": "^29.2.0",
- "jest-util": "^29.4.1",
- "jest-worker": "^29.4.1",
- "micromatch": "^4.0.4",
- "walker": "^1.0.8"
- }
- },
- "jest-leak-detector": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.4.1.tgz",
- "integrity": "sha512-akpZv7TPyGMnH2RimOCgy+hPmWZf55EyFUvymQ4LMsQP8xSPlZumCPtXGoDhFNhUE2039RApZkTQDKU79p/FiQ==",
- "dev": true,
- "requires": {
- "jest-get-type": "^29.2.0",
- "pretty-format": "^29.4.1"
- }
- },
- "jest-matcher-utils": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.4.1.tgz",
- "integrity": "sha512-k5h0u8V4nAEy6lSACepxL/rw78FLDkBnXhZVgFneVpnJONhb2DhZj/Gv4eNe+1XqQ5IhgUcqj745UwH0HJmMnA==",
- "dev": true,
- "requires": {
- "chalk": "^4.0.0",
- "jest-diff": "^29.4.1",
- "jest-get-type": "^29.2.0",
- "pretty-format": "^29.4.1"
- }
- },
- "jest-message-util": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.4.1.tgz",
- "integrity": "sha512-H4/I0cXUaLeCw6FM+i4AwCnOwHRgitdaUFOdm49022YD5nfyr8C/DrbXOBEyJaj+w/y0gGJ57klssOaUiLLQGQ==",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.12.13",
- "@jest/types": "^29.4.1",
- "@types/stack-utils": "^2.0.0",
- "chalk": "^4.0.0",
- "graceful-fs": "^4.2.9",
- "micromatch": "^4.0.4",
- "pretty-format": "^29.4.1",
- "slash": "^3.0.0",
- "stack-utils": "^2.0.3"
- }
- },
- "jest-mock": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.4.1.tgz",
- "integrity": "sha512-MwA4hQ7zBOcgVCVnsM8TzaFLVUD/pFWTfbkY953Y81L5ret3GFRZtmPmRFAjKQSdCKoJvvqOu6Bvfpqlwwb0dQ==",
- "dev": true,
- "requires": {
- "@jest/types": "^29.4.1",
- "@types/node": "*",
- "jest-util": "^29.4.1"
- }
- },
- "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,
- "requires": {}
- },
- "jest-regex-util": {
- "version": "29.2.0",
- "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.2.0.tgz",
- "integrity": "sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA==",
- "dev": true
- },
- "jest-resolve": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.4.1.tgz",
- "integrity": "sha512-j/ZFNV2lm9IJ2wmlq1uYK0Y/1PiyDq9g4HEGsNTNr3viRbJdV+8Lf1SXIiLZXFvyiisu0qUyIXGBnw+OKWkJwQ==",
- "dev": true,
- "requires": {
- "chalk": "^4.0.0",
- "graceful-fs": "^4.2.9",
- "jest-haste-map": "^29.4.1",
- "jest-pnp-resolver": "^1.2.2",
- "jest-util": "^29.4.1",
- "jest-validate": "^29.4.1",
- "resolve": "^1.20.0",
- "resolve.exports": "^2.0.0",
- "slash": "^3.0.0"
- }
- },
- "jest-resolve-dependencies": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.4.1.tgz",
- "integrity": "sha512-Y3QG3M1ncAMxfjbYgtqNXC5B595zmB6e//p/qpA/58JkQXu/IpLDoLeOa8YoYfsSglBKQQzNUqtfGJJT/qLmJg==",
- "dev": true,
- "requires": {
- "jest-regex-util": "^29.2.0",
- "jest-snapshot": "^29.4.1"
- }
- },
- "jest-runner": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.4.1.tgz",
- "integrity": "sha512-8d6XXXi7GtHmsHrnaqBKWxjKb166Eyj/ksSaUYdcBK09VbjPwIgWov1VwSmtupCIz8q1Xv4Qkzt/BTo3ZqiCeg==",
- "dev": true,
- "requires": {
- "@jest/console": "^29.4.1",
- "@jest/environment": "^29.4.1",
- "@jest/test-result": "^29.4.1",
- "@jest/transform": "^29.4.1",
- "@jest/types": "^29.4.1",
- "@types/node": "*",
- "chalk": "^4.0.0",
- "emittery": "^0.13.1",
- "graceful-fs": "^4.2.9",
- "jest-docblock": "^29.2.0",
- "jest-environment-node": "^29.4.1",
- "jest-haste-map": "^29.4.1",
- "jest-leak-detector": "^29.4.1",
- "jest-message-util": "^29.4.1",
- "jest-resolve": "^29.4.1",
- "jest-runtime": "^29.4.1",
- "jest-util": "^29.4.1",
- "jest-watcher": "^29.4.1",
- "jest-worker": "^29.4.1",
- "p-limit": "^3.1.0",
- "source-map-support": "0.5.13"
- }
- },
- "jest-runtime": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.4.1.tgz",
- "integrity": "sha512-UXTMU9uKu2GjYwTtoAw5rn4STxWw/nadOfW7v1sx6LaJYa3V/iymdCLQM6xy3+7C6mY8GfX22vKpgxY171UIoA==",
- "dev": true,
- "requires": {
- "@jest/environment": "^29.4.1",
- "@jest/fake-timers": "^29.4.1",
- "@jest/globals": "^29.4.1",
- "@jest/source-map": "^29.2.0",
- "@jest/test-result": "^29.4.1",
- "@jest/transform": "^29.4.1",
- "@jest/types": "^29.4.1",
- "@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.4.1",
- "jest-message-util": "^29.4.1",
- "jest-mock": "^29.4.1",
- "jest-regex-util": "^29.2.0",
- "jest-resolve": "^29.4.1",
- "jest-snapshot": "^29.4.1",
- "jest-util": "^29.4.1",
- "semver": "^7.3.5",
- "slash": "^3.0.0",
- "strip-bom": "^4.0.0"
- },
- "dependencies": {
- "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,
- "requires": {
- "yallist": "^4.0.0"
- }
- },
- "semver": {
- "version": "7.3.8",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
- "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
- "dev": true,
- "requires": {
- "lru-cache": "^6.0.0"
- }
- },
- "yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "dev": true
- }
- }
- },
- "jest-snapshot": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.4.1.tgz",
- "integrity": "sha512-l4iV8EjGgQWVz3ee/LR9sULDk2pCkqb71bjvlqn+qp90lFwpnulHj4ZBT8nm1hA1C5wowXLc7MGnw321u0tsYA==",
- "dev": true,
- "requires": {
- "@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/traverse": "^7.7.2",
- "@babel/types": "^7.3.3",
- "@jest/expect-utils": "^29.4.1",
- "@jest/transform": "^29.4.1",
- "@jest/types": "^29.4.1",
- "@types/babel__traverse": "^7.0.6",
- "@types/prettier": "^2.1.5",
- "babel-preset-current-node-syntax": "^1.0.0",
- "chalk": "^4.0.0",
- "expect": "^29.4.1",
- "graceful-fs": "^4.2.9",
- "jest-diff": "^29.4.1",
- "jest-get-type": "^29.2.0",
- "jest-haste-map": "^29.4.1",
- "jest-matcher-utils": "^29.4.1",
- "jest-message-util": "^29.4.1",
- "jest-util": "^29.4.1",
- "natural-compare": "^1.4.0",
- "pretty-format": "^29.4.1",
- "semver": "^7.3.5"
- },
- "dependencies": {
- "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,
- "requires": {
- "yallist": "^4.0.0"
- }
- },
- "semver": {
- "version": "7.3.8",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
- "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
- "dev": true,
- "requires": {
- "lru-cache": "^6.0.0"
- }
- },
- "yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "dev": true
- }
- }
- },
- "jest-util": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.4.1.tgz",
- "integrity": "sha512-bQy9FPGxVutgpN4VRc0hk6w7Hx/m6L53QxpDreTZgJd9gfx/AV2MjyPde9tGyZRINAUrSv57p2inGBu2dRLmkQ==",
- "dev": true,
- "requires": {
- "@jest/types": "^29.4.1",
- "@types/node": "*",
- "chalk": "^4.0.0",
- "ci-info": "^3.2.0",
- "graceful-fs": "^4.2.9",
- "picomatch": "^2.2.3"
- }
- },
- "jest-validate": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.4.1.tgz",
- "integrity": "sha512-qNZXcZQdIQx4SfUB/atWnI4/I2HUvhz8ajOSYUu40CSmf9U5emil8EDHgE7M+3j9/pavtk3knlZBDsgFvv/SWw==",
- "dev": true,
- "requires": {
- "@jest/types": "^29.4.1",
- "camelcase": "^6.2.0",
- "chalk": "^4.0.0",
- "jest-get-type": "^29.2.0",
- "leven": "^3.1.0",
- "pretty-format": "^29.4.1"
- },
- "dependencies": {
- "camelcase": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
- "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
- "dev": true
- }
- }
- },
- "jest-watcher": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.4.1.tgz",
- "integrity": "sha512-vFOzflGFs27nU6h8dpnVRER3O2rFtL+VMEwnG0H3KLHcllLsU8y9DchSh0AL/Rg5nN1/wSiQ+P4ByMGpuybaVw==",
- "dev": true,
- "requires": {
- "@jest/test-result": "^29.4.1",
- "@jest/types": "^29.4.1",
- "@types/node": "*",
- "ansi-escapes": "^4.2.1",
- "chalk": "^4.0.0",
- "emittery": "^0.13.1",
- "jest-util": "^29.4.1",
- "string-length": "^4.0.1"
- }
- },
- "jest-worker": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.4.1.tgz",
- "integrity": "sha512-O9doU/S1EBe+yp/mstQ0VpPwpv0Clgn68TkNwGxL6/usX/KUW9Arnn4ag8C3jc6qHcXznhsT5Na1liYzAsuAbQ==",
- "dev": true,
- "requires": {
- "@types/node": "*",
- "jest-util": "^29.4.1",
- "merge-stream": "^2.0.0",
- "supports-color": "^8.0.0"
- },
- "dependencies": {
- "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,
- "requires": {
- "has-flag": "^4.0.0"
- }
- }
- }
- },
- "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
- },
- "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,
- "requires": {
- "argparse": "^1.0.7",
- "esprima": "^4.0.0"
- }
- },
- "jsesc": {
- "version": "2.5.2",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
- "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
- "dev": true
- },
- "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
- },
- "json5": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
- "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
- "dev": true
- },
- "kleur": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
- "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
- "dev": true
- },
- "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
- },
- "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
- },
- "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,
- "requires": {
- "p-locate": "^4.1.0"
- }
- },
- "lodash.memoize": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
- "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==",
- "dev": true
- },
- "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,
- "requires": {
- "yallist": "^3.0.2"
- }
- },
- "make-dir": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
- "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
- "dev": true,
- "requires": {
- "semver": "^6.0.0"
- }
- },
- "make-error": {
- "version": "1.3.6",
- "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
- "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
- "dev": true
- },
- "makeerror": {
- "version": "1.0.12",
- "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
- "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
- "dev": true,
- "requires": {
- "tmpl": "1.0.5"
- }
- },
- "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
- },
- "micromatch": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
- "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
- "dev": true,
- "requires": {
- "braces": "^3.0.2",
- "picomatch": "^2.3.1"
- }
- },
- "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
- },
- "minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
- "requires": {
- "brace-expansion": "^1.1.7"
- }
- },
- "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
- },
- "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-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-releases": {
- "version": "2.0.8",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz",
- "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==",
- "dev": true
- },
- "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
- },
- "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,
- "requires": {
- "path-key": "^3.0.0"
- }
- },
- "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,
- "requires": {
- "wrappy": "1"
- }
- },
- "onetime": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
- "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
- "dev": true,
- "requires": {
- "mimic-fn": "^2.1.0"
- }
- },
- "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,
- "requires": {
- "yocto-queue": "^0.1.0"
- }
- },
- "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,
- "requires": {
- "p-limit": "^2.2.0"
- },
- "dependencies": {
- "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,
- "requires": {
- "p-try": "^2.0.0"
- }
- }
- }
- },
- "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
- },
- "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,
- "requires": {
- "@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"
- }
- },
- "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
- },
- "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
- },
- "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
- },
- "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
- },
- "picocolors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
- "dev": true
- },
- "picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true
- },
- "pirates": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz",
- "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==",
- "dev": true
- },
- "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,
- "requires": {
- "find-up": "^4.0.0"
- }
- },
- "pretty-format": {
- "version": "29.4.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.4.1.tgz",
- "integrity": "sha512-dt/Z761JUVsrIKaY215o1xQJBGlSmTx/h4cSqXqjHLnU1+Kt+mavVE7UgqJJO5ukx5HjSswHfmXz4LjS2oIJfg==",
- "dev": true,
- "requires": {
- "@jest/schemas": "^29.4.0",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- },
- "dependencies": {
- "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
- }
- }
- },
- "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,
- "requires": {
- "kleur": "^3.0.3",
- "sisteransi": "^1.0.5"
- }
- },
- "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
- },
- "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
- },
- "resolve": {
- "version": "1.22.1",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
- "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
- "dev": true,
- "requires": {
- "is-core-module": "^2.9.0",
- "path-parse": "^1.0.7",
- "supports-preserve-symlinks-flag": "^1.0.0"
- }
- },
- "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,
- "requires": {
- "resolve-from": "^5.0.0"
- }
- },
- "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
- },
- "resolve.exports": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.0.tgz",
- "integrity": "sha512-6K/gDlqgQscOlg9fSRpWstA8sYe8rbELsSTNpx+3kTrsVCzvSl0zIvRErM7fdl9ERWDsKnrLnwB+Ne89918XOg==",
- "dev": true
- },
- "semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
- "dev": true
- },
- "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,
- "requires": {
- "shebang-regex": "^3.0.0"
- }
- },
- "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
- },
- "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
- },
- "sisteransi": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
- "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
- "dev": true
- },
- "slash": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
- "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
- "dev": true
- },
- "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
- },
- "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,
- "requires": {
- "buffer-from": "^1.0.0",
- "source-map": "^0.6.0"
- }
- },
- "sprintf-js": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
- "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
- "dev": true
- },
- "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,
- "requires": {
- "escape-string-regexp": "^2.0.0"
- }
- },
- "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,
- "requires": {
- "char-regex": "^1.0.2",
- "strip-ansi": "^6.0.0"
- }
- },
- "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,
- "requires": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- }
- },
- "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,
- "requires": {
- "ansi-regex": "^5.0.1"
- }
- },
- "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
- },
- "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
- },
- "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
- },
- "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,
- "requires": {
- "has-flag": "^4.0.0"
- }
- },
- "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
- },
- "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,
- "requires": {
- "@istanbuljs/schema": "^0.1.2",
- "glob": "^7.1.4",
- "minimatch": "^3.0.4"
- }
- },
- "tmpl": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
- "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
- "dev": true
- },
- "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
- },
- "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,
- "requires": {
- "is-number": "^7.0.0"
- }
- },
- "ts-jest": {
- "version": "29.0.5",
- "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.5.tgz",
- "integrity": "sha512-PL3UciSgIpQ7f6XjVOmbi96vmDHUqAyqDr8YxzopDqX3kfgYtX1cuNeBjP+L9sFXi6nzsGGA6R3fP3DDDJyrxA==",
- "dev": true,
- "requires": {
- "bs-logger": "0.x",
- "fast-json-stable-stringify": "2.x",
- "jest-util": "^29.0.0",
- "json5": "^2.2.3",
- "lodash.memoize": "4.x",
- "make-error": "1.x",
- "semver": "7.x",
- "yargs-parser": "^21.0.1"
- },
- "dependencies": {
- "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,
- "requires": {
- "yallist": "^4.0.0"
- }
- },
- "semver": {
- "version": "7.3.8",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
- "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
- "dev": true,
- "requires": {
- "lru-cache": "^6.0.0"
- }
- },
- "yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "dev": true
- }
- }
- },
- "ts-node": {
- "version": "10.9.1",
- "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
- "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==",
- "dev": true,
- "requires": {
- "@cspotcode/source-map-support": "^0.8.0",
- "@tsconfig/node10": "^1.0.7",
- "@tsconfig/node12": "^1.0.7",
- "@tsconfig/node14": "^1.0.0",
- "@tsconfig/node16": "^1.0.2",
- "acorn": "^8.4.1",
- "acorn-walk": "^8.1.1",
- "arg": "^4.1.0",
- "create-require": "^1.1.0",
- "diff": "^4.0.1",
- "make-error": "^1.1.1",
- "v8-compile-cache-lib": "^3.0.1",
- "yn": "3.1.1"
- }
- },
- "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
- },
- "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
- },
- "typescript": {
- "version": "4.9.4",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
- "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==",
- "dev": true
- },
- "update-browserslist-db": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
- "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==",
- "dev": true,
- "requires": {
- "escalade": "^3.1.1",
- "picocolors": "^1.0.0"
- }
- },
- "v8-compile-cache-lib": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
- "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
- "dev": true
- },
- "v8-to-istanbul": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz",
- "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==",
- "dev": true,
- "requires": {
- "@jridgewell/trace-mapping": "^0.3.12",
- "@types/istanbul-lib-coverage": "^2.0.1",
- "convert-source-map": "^1.6.0"
- },
- "dependencies": {
- "@jridgewell/trace-mapping": {
- "version": "0.3.17",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
- "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
- "dev": true,
- "requires": {
- "@jridgewell/resolve-uri": "3.1.0",
- "@jridgewell/sourcemap-codec": "1.4.14"
- }
- },
- "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
- }
- }
- },
- "walker": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
- "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
- "dev": true,
- "requires": {
- "makeerror": "1.0.12"
- }
- },
- "which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
- "requires": {
- "isexe": "^2.0.0"
- }
- },
- "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,
- "requires": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- }
- },
- "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
- },
- "write-file-atomic": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.0.tgz",
- "integrity": "sha512-R7NYMnHSlV42K54lwY9lvW6MnSm1HSJqZL3xiSgi9E7//FYaI74r2G0rd+/X6VAMkHEdzxQaU5HUOXWUz5kA/w==",
- "dev": true,
- "requires": {
- "imurmurhash": "^0.1.4",
- "signal-exit": "^3.0.7"
- }
- },
- "y18n": {
- "version": "5.0.8",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
- "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
- "dev": true
- },
- "yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
- "dev": true
- },
- "yargs": {
- "version": "17.6.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz",
- "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==",
- "dev": true,
- "requires": {
- "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"
- }
- },
- "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
- },
- "yn": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
- "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
- "dev": true
- },
- "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
- }
}
}
diff --git a/deployment/cdk-solution-helper/package.json b/deployment/cdk-solution-helper/package.json
index dbd844ca..97176fb8 100644
--- a/deployment/cdk-solution-helper/package.json
+++ b/deployment/cdk-solution-helper/package.json
@@ -3,22 +3,26 @@
"version": "1.0.0",
"description": "helper to update references in cdk generated cfn template and package lambda assets",
"main": "index.js",
+ "author": {
+ "name": "Amazon Web Services",
+ "url": "https://aws.amazon.com/solutions",
+ "organization": true
+ },
"scripts": {
"test": "jest"
},
- "author": "aws-solutions",
"license": "Apache-2.0",
"devDependencies": {
"@types/adm-zip": "^0.5.0",
- "@types/jest": "^29.4.0",
- "@types/node": "^18.11.18",
- "jest": "^29.4.1",
- "ts-jest": "^29.0.5",
+ "@types/jest": "^29.5.3",
+ "@types/node": "^18.16.19",
+ "jest": "^29.6.1",
+ "ts-jest": "^29.1.1",
"ts-node": "^10.9.1",
- "typescript": "^4.9.4"
+ "typescript": "^5.1.6"
},
"dependencies": {
"adm-zip": "^0.5.10",
- "aws-cdk-lib": "^2.63.0"
+ "aws-cdk-lib": "^2.87.0"
}
}
diff --git a/deployment/run-unit-tests.sh b/deployment/run-unit-tests.sh
deleted file mode 100755
index 0fcb50d1..00000000
--- a/deployment/run-unit-tests.sh
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/env bash
-#
-# Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
-# with the License. A copy of the License is located at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES
-# OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
-# and limitations under the License.
-#
-
-
-set -e #fail script if any commands fail
-
-#relevant directories
-source_template_dir=$PWD #/deployment
-root_dir="$source_template_dir/.."
-cdk_src_dir="$source_template_dir/../source"
-lamda_src_dir="$source_template_dir/../source/lambda"
-coverage_reports_dir="$source_template_dir/coverage-reports"
-
-
-
-echo "------------------------------------------------------------------------------"
-echo "Running Unit Tests"
-echo "------------------------------------------------------------------------------"
-echo "Working Directory: $PWD"
-echo "CDK Sources Directory: $cdk_src_dir"
-echo "Lambda Sources Directory: $lamda_src_dir"
-echo "Coverage Reports Directory: $coverage_reports_dir"
-
-mkdir -p "$coverage_reports_dir"
-
-echo "------------------------------------------------------------------------------"
-echo "Installing Tox"
-echo "------------------------------------------------------------------------------"
-cd "$root_dir" || (echo "$root_dir does not exist" && exit 1)
-pip install tox
-
-echo "------------------------------------------------------------------------------"
-echo "Starting CDK Unit Test"
-echo "------------------------------------------------------------------------------"
-#tox runs cdk relative to source/infrastructure
-cdk_coverage_report_path="$coverage_reports_dir/cdk-coverage"
-echo "running tests and saving coverage to $coverage_reports_dir"
-tox -e cdk --exit-and-dump-after 1200 -- --coverage --coverageDirectory "$cdk_coverage_report_path"
-
-echo "------------------------------------------------------------------------------"
-echo "Starting Lambda Unit Tests"
-echo "------------------------------------------------------------------------------"
-#tox runs lambda relative to source/app
-lambda_coverage_report_path="$coverage_reports_dir/lambda-coverage.xml"
-echo "running tests and saving coverage to $lambda_coverage_report_path"
-tox -e lambda --exit-and-dump-after 1200 -- --cov --cov-report "xml:$lambda_coverage_report_path"
-sed -i -e "s|||g" $lambda_coverage_report_path
-
-
-echo "------------------------------------------------------------------------------"
-echo "Starting CLI Unit Tests"
-echo "------------------------------------------------------------------------------"
-#tox runs cli tests relative to source/cli
-cli_coverage_report_path="$coverage_reports_dir/cli-coverage.xml"
-echo "running tests and saving coverage to $cli_coverage_report_path"
-tox -e cli --exit-and-dump-after 1200 -- --cov --cov-report "xml:$cli_coverage_report_path"
-sed -i -e "s|||g" $cli_coverage_report_path
-
-# Return to calling dir (/deployment)
-cd $source_template_dir
diff --git a/source/infrastructure/global.d.ts b/global.d.ts
similarity index 100%
rename from source/infrastructure/global.d.ts
rename to global.d.ts
diff --git a/jest.config.json b/jest.config.json
new file mode 100644
index 00000000..385c51a8
--- /dev/null
+++ b/jest.config.json
@@ -0,0 +1,43 @@
+{
+ "roots": [
+ "/source/instance-scheduler/tests"
+ ],
+ "transform": {
+ "^.+\\.tsx?$": "ts-jest"
+ },
+ "reporters": [
+ "default",
+ [
+ "jest-junit",
+ {
+ "outputDirectory": "deployment/test-reports",
+ "outputName": "cdk-test-report.xml"
+ }
+ ]
+ ],
+ "testMatch": [
+ "**/lib/instance-scheduler/tests/**/?(*.)+(spec|test).js?(x)",
+ "**/*.test.ts"
+ ],
+ "clearMocks": true,
+ "collectCoverage": true,
+ "coverageReporters": [
+ "json",
+ "lcov",
+ "clover",
+ "cobertura",
+ "text"
+ ],
+ "coverageDirectory": "coverage",
+ "coveragePathIgnorePatterns": [
+ "/node_modules/"
+ ],
+ "testPathIgnorePatterns": [
+ "/node_modules/"
+ ],
+ "watchPathIgnorePatterns": [
+ "/node_modules/",
+ "/source/"
+ ],
+ "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"."
+}
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 00000000..2a402f5d
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,12513 @@
+{
+ "name": "instance-scheduler-on-aws",
+ "version": "1.5.1",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "instance-scheduler-on-aws",
+ "version": "1.5.1",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-cdk/aws-lambda-python-alpha": "^2.87.0-alpha.0",
+ "@aws-cdk/aws-servicecatalogappregistry-alpha": "^2.87.0-alpha.0",
+ "@aws-sdk/client-dynamodb": "^3.369.0",
+ "@aws-sdk/client-ec2": "^3.369.0",
+ "@aws-sdk/client-rds": "^3.369.0",
+ "@aws-sdk/client-ssm": "^3.369.0",
+ "@aws-solutions-constructs/aws-lambda-dynamodb": "^2.41.0",
+ "aws-cdk-lib": "^2.87.0",
+ "cdk-nag": "^2.27.67",
+ "constructs": "^10.0.5",
+ "source-map-support": "^0.5.21"
+ },
+ "devDependencies": {
+ "@types/jest": "^29.5.3",
+ "@types/node": "^18",
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
+ "aws-cdk": "^2.87.0",
+ "esbuild": "^0.18.11",
+ "eslint": "^8.44.0",
+ "eslint-config-prettier": "^8.8.0",
+ "eslint-plugin-header": "^3.1.1",
+ "eslint-plugin-import": "^2.27.5",
+ "eslint-plugin-prettier": "^5.0.0",
+ "jest": "^29.6.1",
+ "jest-extended": "^4.0.0",
+ "jest-junit": "^16.0.0",
+ "npm-check-updates": "^16",
+ "projen": "^0.71.133",
+ "ts-jest": "^29.1.1",
+ "ts-node": "^10.9.1",
+ "typescript": "^5.1.6"
+ },
+ "engines": {
+ "node": ">= 18.0.0"
+ }
+ },
+ "node_modules/@aashutoshrathi/word-wrap": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
+ "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "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/@aws-cdk/asset-awscli-v1": {
+ "version": "2.2.200",
+ "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.200.tgz",
+ "integrity": "sha512-Kf5J8DfJK4wZFWT2Myca0lhwke7LwHcHBo+4TvWOGJrFVVKVuuiLCkzPPRBQQVDj0Vtn2NBokZAz8pfMpAqAKg=="
+ },
+ "node_modules/@aws-cdk/asset-kubectl-v20": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@aws-cdk/asset-kubectl-v20/-/asset-kubectl-v20-2.1.2.tgz",
+ "integrity": "sha512-3M2tELJOxQv0apCIiuKQ4pAbncz9GuLwnKFqxifWfe77wuMxyTRPmxssYHs42ePqzap1LT6GDcPygGs+hHstLg=="
+ },
+ "node_modules/@aws-cdk/asset-node-proxy-agent-v5": {
+ "version": "2.0.165",
+ "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v5/-/asset-node-proxy-agent-v5-2.0.165.tgz",
+ "integrity": "sha512-bsyLQD/vqXQcc9RDmlM1XqiFNO/yewgVFXmkMcQkndJbmE/jgYkzewwYGrBlfL725hGLQipXq19+jwWwdsXQqg=="
+ },
+ "node_modules/@aws-cdk/aws-lambda-python-alpha": {
+ "version": "2.87.0-alpha.0",
+ "resolved": "https://registry.npmjs.org/@aws-cdk/aws-lambda-python-alpha/-/aws-lambda-python-alpha-2.87.0-alpha.0.tgz",
+ "integrity": "sha512-+S9lCwLzcFrF/3Y6VOuRy6O5ZgOHpaJ1bCddl23B3Txg0sJ00qNGyuwtozvu/5CtAPnxSTvQEUWxXJdP7Lw2Fg==",
+ "engines": {
+ "node": ">= 14.15.0"
+ },
+ "peerDependencies": {
+ "aws-cdk-lib": "2.87.0",
+ "constructs": "^10.0.0"
+ }
+ },
+ "node_modules/@aws-cdk/aws-servicecatalogappregistry-alpha": {
+ "version": "2.87.0-alpha.0",
+ "resolved": "https://registry.npmjs.org/@aws-cdk/aws-servicecatalogappregistry-alpha/-/aws-servicecatalogappregistry-alpha-2.87.0-alpha.0.tgz",
+ "integrity": "sha512-iSpXYqUKWtZM1TorUdk9e55aG7IJyCQncFtxBUeAdO4MjUDM7kGeLk8SJqYk1S9KeA0HPFLRJakbVd0NLnVKUA==",
+ "engines": {
+ "node": ">= 14.15.0"
+ },
+ "peerDependencies": {
+ "aws-cdk-lib": "2.87.0",
+ "constructs": "^10.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/crc32": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz",
+ "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==",
+ "dependencies": {
+ "@aws-crypto/util": "^3.0.0",
+ "@aws-sdk/types": "^3.222.0",
+ "tslib": "^1.11.1"
+ }
+ },
+ "node_modules/@aws-crypto/crc32/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+ },
+ "node_modules/@aws-crypto/ie11-detection": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz",
+ "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==",
+ "dependencies": {
+ "tslib": "^1.11.1"
+ }
+ },
+ "node_modules/@aws-crypto/ie11-detection/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+ },
+ "node_modules/@aws-crypto/sha256-browser": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz",
+ "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==",
+ "dependencies": {
+ "@aws-crypto/ie11-detection": "^3.0.0",
+ "@aws-crypto/sha256-js": "^3.0.0",
+ "@aws-crypto/supports-web-crypto": "^3.0.0",
+ "@aws-crypto/util": "^3.0.0",
+ "@aws-sdk/types": "^3.222.0",
+ "@aws-sdk/util-locate-window": "^3.0.0",
+ "@aws-sdk/util-utf8-browser": "^3.0.0",
+ "tslib": "^1.11.1"
+ }
+ },
+ "node_modules/@aws-crypto/sha256-browser/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+ },
+ "node_modules/@aws-crypto/sha256-js": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz",
+ "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==",
+ "dependencies": {
+ "@aws-crypto/util": "^3.0.0",
+ "@aws-sdk/types": "^3.222.0",
+ "tslib": "^1.11.1"
+ }
+ },
+ "node_modules/@aws-crypto/sha256-js/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+ },
+ "node_modules/@aws-crypto/supports-web-crypto": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz",
+ "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==",
+ "dependencies": {
+ "tslib": "^1.11.1"
+ }
+ },
+ "node_modules/@aws-crypto/supports-web-crypto/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+ },
+ "node_modules/@aws-crypto/util": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz",
+ "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==",
+ "dependencies": {
+ "@aws-sdk/types": "^3.222.0",
+ "@aws-sdk/util-utf8-browser": "^3.0.0",
+ "tslib": "^1.11.1"
+ }
+ },
+ "node_modules/@aws-crypto/util/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
+ },
+ "node_modules/@aws-sdk/client-dynamodb": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.369.0.tgz",
+ "integrity": "sha512-BBE8ktqqgXvG4r1yWmRZYR/gqaebtmeWFQMwbr0hTMLEw5joeVWLHywLHd4uNMS9uCNEEmaSWAlVyC6LfMc7Mw==",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "3.0.0",
+ "@aws-crypto/sha256-js": "3.0.0",
+ "@aws-sdk/client-sts": "3.369.0",
+ "@aws-sdk/credential-provider-node": "3.369.0",
+ "@aws-sdk/middleware-endpoint-discovery": "3.369.0",
+ "@aws-sdk/middleware-host-header": "3.369.0",
+ "@aws-sdk/middleware-logger": "3.369.0",
+ "@aws-sdk/middleware-recursion-detection": "3.369.0",
+ "@aws-sdk/middleware-signing": "3.369.0",
+ "@aws-sdk/middleware-user-agent": "3.369.0",
+ "@aws-sdk/types": "3.369.0",
+ "@aws-sdk/util-endpoints": "3.369.0",
+ "@aws-sdk/util-user-agent-browser": "3.369.0",
+ "@aws-sdk/util-user-agent-node": "3.369.0",
+ "@smithy/config-resolver": "^1.0.1",
+ "@smithy/fetch-http-handler": "^1.0.1",
+ "@smithy/hash-node": "^1.0.1",
+ "@smithy/invalid-dependency": "^1.0.1",
+ "@smithy/middleware-content-length": "^1.0.1",
+ "@smithy/middleware-endpoint": "^1.0.1",
+ "@smithy/middleware-retry": "^1.0.2",
+ "@smithy/middleware-serde": "^1.0.1",
+ "@smithy/middleware-stack": "^1.0.1",
+ "@smithy/node-config-provider": "^1.0.1",
+ "@smithy/node-http-handler": "^1.0.2",
+ "@smithy/protocol-http": "^1.0.1",
+ "@smithy/smithy-client": "^1.0.3",
+ "@smithy/types": "^1.1.0",
+ "@smithy/url-parser": "^1.0.1",
+ "@smithy/util-base64": "^1.0.1",
+ "@smithy/util-body-length-browser": "^1.0.1",
+ "@smithy/util-body-length-node": "^1.0.1",
+ "@smithy/util-defaults-mode-browser": "^1.0.1",
+ "@smithy/util-defaults-mode-node": "^1.0.1",
+ "@smithy/util-retry": "^1.0.2",
+ "@smithy/util-utf8": "^1.0.1",
+ "@smithy/util-waiter": "^1.0.1",
+ "tslib": "^2.5.0",
+ "uuid": "^8.3.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-ec2": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-ec2/-/client-ec2-3.369.0.tgz",
+ "integrity": "sha512-4nI58BxUlpCae0K9SGB2qPu63RpnPuAZkRnW/i+UEop0/kgXVcaWXx1G6nyLGZPTpJQvxnrfw7yrosSQUsv4Fg==",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "3.0.0",
+ "@aws-crypto/sha256-js": "3.0.0",
+ "@aws-sdk/client-sts": "3.369.0",
+ "@aws-sdk/credential-provider-node": "3.369.0",
+ "@aws-sdk/middleware-host-header": "3.369.0",
+ "@aws-sdk/middleware-logger": "3.369.0",
+ "@aws-sdk/middleware-recursion-detection": "3.369.0",
+ "@aws-sdk/middleware-sdk-ec2": "3.369.0",
+ "@aws-sdk/middleware-signing": "3.369.0",
+ "@aws-sdk/middleware-user-agent": "3.369.0",
+ "@aws-sdk/types": "3.369.0",
+ "@aws-sdk/util-endpoints": "3.369.0",
+ "@aws-sdk/util-user-agent-browser": "3.369.0",
+ "@aws-sdk/util-user-agent-node": "3.369.0",
+ "@smithy/config-resolver": "^1.0.1",
+ "@smithy/fetch-http-handler": "^1.0.1",
+ "@smithy/hash-node": "^1.0.1",
+ "@smithy/invalid-dependency": "^1.0.1",
+ "@smithy/middleware-content-length": "^1.0.1",
+ "@smithy/middleware-endpoint": "^1.0.1",
+ "@smithy/middleware-retry": "^1.0.2",
+ "@smithy/middleware-serde": "^1.0.1",
+ "@smithy/middleware-stack": "^1.0.1",
+ "@smithy/node-config-provider": "^1.0.1",
+ "@smithy/node-http-handler": "^1.0.2",
+ "@smithy/protocol-http": "^1.0.1",
+ "@smithy/smithy-client": "^1.0.3",
+ "@smithy/types": "^1.1.0",
+ "@smithy/url-parser": "^1.0.1",
+ "@smithy/util-base64": "^1.0.1",
+ "@smithy/util-body-length-browser": "^1.0.1",
+ "@smithy/util-body-length-node": "^1.0.1",
+ "@smithy/util-defaults-mode-browser": "^1.0.1",
+ "@smithy/util-defaults-mode-node": "^1.0.1",
+ "@smithy/util-retry": "^1.0.2",
+ "@smithy/util-utf8": "^1.0.1",
+ "@smithy/util-waiter": "^1.0.1",
+ "fast-xml-parser": "4.2.5",
+ "tslib": "^2.5.0",
+ "uuid": "^8.3.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-rds": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-rds/-/client-rds-3.369.0.tgz",
+ "integrity": "sha512-ABcxq8vdK2qJ29DhlgYO85Gp25QB64J3jg6wY8ysrUI8FKVE2c3aeGlza3n7TV63EcMPteRBuEQz0Rt1FyoHRg==",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "3.0.0",
+ "@aws-crypto/sha256-js": "3.0.0",
+ "@aws-sdk/client-sts": "3.369.0",
+ "@aws-sdk/credential-provider-node": "3.369.0",
+ "@aws-sdk/middleware-host-header": "3.369.0",
+ "@aws-sdk/middleware-logger": "3.369.0",
+ "@aws-sdk/middleware-recursion-detection": "3.369.0",
+ "@aws-sdk/middleware-sdk-rds": "3.369.0",
+ "@aws-sdk/middleware-signing": "3.369.0",
+ "@aws-sdk/middleware-user-agent": "3.369.0",
+ "@aws-sdk/types": "3.369.0",
+ "@aws-sdk/util-endpoints": "3.369.0",
+ "@aws-sdk/util-user-agent-browser": "3.369.0",
+ "@aws-sdk/util-user-agent-node": "3.369.0",
+ "@smithy/config-resolver": "^1.0.1",
+ "@smithy/fetch-http-handler": "^1.0.1",
+ "@smithy/hash-node": "^1.0.1",
+ "@smithy/invalid-dependency": "^1.0.1",
+ "@smithy/middleware-content-length": "^1.0.1",
+ "@smithy/middleware-endpoint": "^1.0.1",
+ "@smithy/middleware-retry": "^1.0.2",
+ "@smithy/middleware-serde": "^1.0.1",
+ "@smithy/middleware-stack": "^1.0.1",
+ "@smithy/node-config-provider": "^1.0.1",
+ "@smithy/node-http-handler": "^1.0.2",
+ "@smithy/protocol-http": "^1.0.1",
+ "@smithy/smithy-client": "^1.0.3",
+ "@smithy/types": "^1.1.0",
+ "@smithy/url-parser": "^1.0.1",
+ "@smithy/util-base64": "^1.0.1",
+ "@smithy/util-body-length-browser": "^1.0.1",
+ "@smithy/util-body-length-node": "^1.0.1",
+ "@smithy/util-defaults-mode-browser": "^1.0.1",
+ "@smithy/util-defaults-mode-node": "^1.0.1",
+ "@smithy/util-retry": "^1.0.2",
+ "@smithy/util-utf8": "^1.0.1",
+ "@smithy/util-waiter": "^1.0.1",
+ "fast-xml-parser": "4.2.5",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-ssm": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-ssm/-/client-ssm-3.369.0.tgz",
+ "integrity": "sha512-AmqkFCVAcbg09XFEYGHzuYOqDUIJntPLzRy/hBPud7FEXlk1ip0ZBZAIO/uWjjoOg1rEdDB/m/ivAQ3rxZel2g==",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "3.0.0",
+ "@aws-crypto/sha256-js": "3.0.0",
+ "@aws-sdk/client-sts": "3.369.0",
+ "@aws-sdk/credential-provider-node": "3.369.0",
+ "@aws-sdk/middleware-host-header": "3.369.0",
+ "@aws-sdk/middleware-logger": "3.369.0",
+ "@aws-sdk/middleware-recursion-detection": "3.369.0",
+ "@aws-sdk/middleware-signing": "3.369.0",
+ "@aws-sdk/middleware-user-agent": "3.369.0",
+ "@aws-sdk/types": "3.369.0",
+ "@aws-sdk/util-endpoints": "3.369.0",
+ "@aws-sdk/util-user-agent-browser": "3.369.0",
+ "@aws-sdk/util-user-agent-node": "3.369.0",
+ "@smithy/config-resolver": "^1.0.1",
+ "@smithy/fetch-http-handler": "^1.0.1",
+ "@smithy/hash-node": "^1.0.1",
+ "@smithy/invalid-dependency": "^1.0.1",
+ "@smithy/middleware-content-length": "^1.0.1",
+ "@smithy/middleware-endpoint": "^1.0.1",
+ "@smithy/middleware-retry": "^1.0.2",
+ "@smithy/middleware-serde": "^1.0.1",
+ "@smithy/middleware-stack": "^1.0.1",
+ "@smithy/node-config-provider": "^1.0.1",
+ "@smithy/node-http-handler": "^1.0.2",
+ "@smithy/protocol-http": "^1.0.1",
+ "@smithy/smithy-client": "^1.0.3",
+ "@smithy/types": "^1.1.0",
+ "@smithy/url-parser": "^1.0.1",
+ "@smithy/util-base64": "^1.0.1",
+ "@smithy/util-body-length-browser": "^1.0.1",
+ "@smithy/util-body-length-node": "^1.0.1",
+ "@smithy/util-defaults-mode-browser": "^1.0.1",
+ "@smithy/util-defaults-mode-node": "^1.0.1",
+ "@smithy/util-retry": "^1.0.2",
+ "@smithy/util-utf8": "^1.0.1",
+ "@smithy/util-waiter": "^1.0.1",
+ "tslib": "^2.5.0",
+ "uuid": "^8.3.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-sso": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.369.0.tgz",
+ "integrity": "sha512-SjJd9QGT9ccHOY64qnMfvVjrneBORIx/k8OdtL0nV2wemPqCM9uAm+TYZ01E91D/+lfXS+lLMGSidSA39PMIOA==",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "3.0.0",
+ "@aws-crypto/sha256-js": "3.0.0",
+ "@aws-sdk/middleware-host-header": "3.369.0",
+ "@aws-sdk/middleware-logger": "3.369.0",
+ "@aws-sdk/middleware-recursion-detection": "3.369.0",
+ "@aws-sdk/middleware-user-agent": "3.369.0",
+ "@aws-sdk/types": "3.369.0",
+ "@aws-sdk/util-endpoints": "3.369.0",
+ "@aws-sdk/util-user-agent-browser": "3.369.0",
+ "@aws-sdk/util-user-agent-node": "3.369.0",
+ "@smithy/config-resolver": "^1.0.1",
+ "@smithy/fetch-http-handler": "^1.0.1",
+ "@smithy/hash-node": "^1.0.1",
+ "@smithy/invalid-dependency": "^1.0.1",
+ "@smithy/middleware-content-length": "^1.0.1",
+ "@smithy/middleware-endpoint": "^1.0.1",
+ "@smithy/middleware-retry": "^1.0.2",
+ "@smithy/middleware-serde": "^1.0.1",
+ "@smithy/middleware-stack": "^1.0.1",
+ "@smithy/node-config-provider": "^1.0.1",
+ "@smithy/node-http-handler": "^1.0.2",
+ "@smithy/protocol-http": "^1.0.1",
+ "@smithy/smithy-client": "^1.0.3",
+ "@smithy/types": "^1.1.0",
+ "@smithy/url-parser": "^1.0.1",
+ "@smithy/util-base64": "^1.0.1",
+ "@smithy/util-body-length-browser": "^1.0.1",
+ "@smithy/util-body-length-node": "^1.0.1",
+ "@smithy/util-defaults-mode-browser": "^1.0.1",
+ "@smithy/util-defaults-mode-node": "^1.0.1",
+ "@smithy/util-retry": "^1.0.2",
+ "@smithy/util-utf8": "^1.0.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-sso-oidc": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.369.0.tgz",
+ "integrity": "sha512-NOnsRrkHMss9pE68uTPMEt1KoW6eWt4ZCesJayCOiIgmIA/AhXHz06IBCYJ9eu9Xbu/55FDr4X3VCtUf7Rfh6g==",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "3.0.0",
+ "@aws-crypto/sha256-js": "3.0.0",
+ "@aws-sdk/middleware-host-header": "3.369.0",
+ "@aws-sdk/middleware-logger": "3.369.0",
+ "@aws-sdk/middleware-recursion-detection": "3.369.0",
+ "@aws-sdk/middleware-user-agent": "3.369.0",
+ "@aws-sdk/types": "3.369.0",
+ "@aws-sdk/util-endpoints": "3.369.0",
+ "@aws-sdk/util-user-agent-browser": "3.369.0",
+ "@aws-sdk/util-user-agent-node": "3.369.0",
+ "@smithy/config-resolver": "^1.0.1",
+ "@smithy/fetch-http-handler": "^1.0.1",
+ "@smithy/hash-node": "^1.0.1",
+ "@smithy/invalid-dependency": "^1.0.1",
+ "@smithy/middleware-content-length": "^1.0.1",
+ "@smithy/middleware-endpoint": "^1.0.1",
+ "@smithy/middleware-retry": "^1.0.2",
+ "@smithy/middleware-serde": "^1.0.1",
+ "@smithy/middleware-stack": "^1.0.1",
+ "@smithy/node-config-provider": "^1.0.1",
+ "@smithy/node-http-handler": "^1.0.2",
+ "@smithy/protocol-http": "^1.0.1",
+ "@smithy/smithy-client": "^1.0.3",
+ "@smithy/types": "^1.1.0",
+ "@smithy/url-parser": "^1.0.1",
+ "@smithy/util-base64": "^1.0.1",
+ "@smithy/util-body-length-browser": "^1.0.1",
+ "@smithy/util-body-length-node": "^1.0.1",
+ "@smithy/util-defaults-mode-browser": "^1.0.1",
+ "@smithy/util-defaults-mode-node": "^1.0.1",
+ "@smithy/util-retry": "^1.0.2",
+ "@smithy/util-utf8": "^1.0.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-sts": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.369.0.tgz",
+ "integrity": "sha512-kyZl654U27gsQX9UjiiO4CX5M6kHwzDouwbhjc5HshQld/lUbJQ4uPpAwhlbZiqnzGeB639MdAGaSwrOOw2ixw==",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "3.0.0",
+ "@aws-crypto/sha256-js": "3.0.0",
+ "@aws-sdk/credential-provider-node": "3.369.0",
+ "@aws-sdk/middleware-host-header": "3.369.0",
+ "@aws-sdk/middleware-logger": "3.369.0",
+ "@aws-sdk/middleware-recursion-detection": "3.369.0",
+ "@aws-sdk/middleware-sdk-sts": "3.369.0",
+ "@aws-sdk/middleware-signing": "3.369.0",
+ "@aws-sdk/middleware-user-agent": "3.369.0",
+ "@aws-sdk/types": "3.369.0",
+ "@aws-sdk/util-endpoints": "3.369.0",
+ "@aws-sdk/util-user-agent-browser": "3.369.0",
+ "@aws-sdk/util-user-agent-node": "3.369.0",
+ "@smithy/config-resolver": "^1.0.1",
+ "@smithy/fetch-http-handler": "^1.0.1",
+ "@smithy/hash-node": "^1.0.1",
+ "@smithy/invalid-dependency": "^1.0.1",
+ "@smithy/middleware-content-length": "^1.0.1",
+ "@smithy/middleware-endpoint": "^1.0.1",
+ "@smithy/middleware-retry": "^1.0.1",
+ "@smithy/middleware-serde": "^1.0.1",
+ "@smithy/middleware-stack": "^1.0.1",
+ "@smithy/node-config-provider": "^1.0.1",
+ "@smithy/node-http-handler": "^1.0.1",
+ "@smithy/protocol-http": "^1.1.0",
+ "@smithy/smithy-client": "^1.0.2",
+ "@smithy/types": "^1.1.0",
+ "@smithy/url-parser": "^1.0.1",
+ "@smithy/util-base64": "^1.0.1",
+ "@smithy/util-body-length-browser": "^1.0.1",
+ "@smithy/util-body-length-node": "^1.0.1",
+ "@smithy/util-defaults-mode-browser": "^1.0.1",
+ "@smithy/util-defaults-mode-node": "^1.0.1",
+ "@smithy/util-retry": "^1.0.1",
+ "@smithy/util-utf8": "^1.0.1",
+ "fast-xml-parser": "4.2.5",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-env": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.369.0.tgz",
+ "integrity": "sha512-EZUXGLjnun5t5/dVYJ9yyOwPAJktOdLEQSwtw7Q9XOxaNqVFFz9EU+TwYraV4WZ3CFRNn7GEIctVlXAHVFLm/w==",
+ "dependencies": {
+ "@aws-sdk/types": "3.369.0",
+ "@smithy/property-provider": "^1.0.1",
+ "@smithy/types": "^1.1.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-ini": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.369.0.tgz",
+ "integrity": "sha512-12XXd4gnrn05adio/xPF8Nxl99L2FFzksbFILDIfSni7nLDX0m2XprnkswQiCKSbfDIQQsgnnh2F+HhorLuqfQ==",
+ "dependencies": {
+ "@aws-sdk/credential-provider-env": "3.369.0",
+ "@aws-sdk/credential-provider-process": "3.369.0",
+ "@aws-sdk/credential-provider-sso": "3.369.0",
+ "@aws-sdk/credential-provider-web-identity": "3.369.0",
+ "@aws-sdk/types": "3.369.0",
+ "@smithy/credential-provider-imds": "^1.0.1",
+ "@smithy/property-provider": "^1.0.1",
+ "@smithy/shared-ini-file-loader": "^1.0.1",
+ "@smithy/types": "^1.1.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-node": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.369.0.tgz",
+ "integrity": "sha512-vxX4s33EpRDh7OhKBDVAPxdBxVHPOOj1r7nN6f0hZLw5WPeeffSjLqw+MnFj33gSO7Htnt+Q0cAJQzeY5G8q3A==",
+ "dependencies": {
+ "@aws-sdk/credential-provider-env": "3.369.0",
+ "@aws-sdk/credential-provider-ini": "3.369.0",
+ "@aws-sdk/credential-provider-process": "3.369.0",
+ "@aws-sdk/credential-provider-sso": "3.369.0",
+ "@aws-sdk/credential-provider-web-identity": "3.369.0",
+ "@aws-sdk/types": "3.369.0",
+ "@smithy/credential-provider-imds": "^1.0.1",
+ "@smithy/property-provider": "^1.0.1",
+ "@smithy/shared-ini-file-loader": "^1.0.1",
+ "@smithy/types": "^1.1.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-process": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.369.0.tgz",
+ "integrity": "sha512-OyasKV3mZz6TRSxczRnyZoifrtYwqGBxtr75YP37cm/JkecDshHXRcE8Jt9LyBg/93oWfKou03WVQiY9UIDJGQ==",
+ "dependencies": {
+ "@aws-sdk/types": "3.369.0",
+ "@smithy/property-provider": "^1.0.1",
+ "@smithy/shared-ini-file-loader": "^1.0.1",
+ "@smithy/types": "^1.1.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-sso": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.369.0.tgz",
+ "integrity": "sha512-qXbEsmgFpGPbRVnwBYPxL53wQuue0+Z8tVu877itbrzpHm61AuQ04Hn8T1boKrr40excDuxiSrCX5oCKRG4srQ==",
+ "dependencies": {
+ "@aws-sdk/client-sso": "3.369.0",
+ "@aws-sdk/token-providers": "3.369.0",
+ "@aws-sdk/types": "3.369.0",
+ "@smithy/property-provider": "^1.0.1",
+ "@smithy/shared-ini-file-loader": "^1.0.1",
+ "@smithy/types": "^1.1.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-web-identity": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.369.0.tgz",
+ "integrity": "sha512-oFGxC839pQTJ6djFEBuokSi3/jNjNMVgZSpg26Z23V/r3vKRSgXfVmeus1FLYIWg0jO7KFsMPo9eVJW6auzw6w==",
+ "dependencies": {
+ "@aws-sdk/types": "3.369.0",
+ "@smithy/property-provider": "^1.0.1",
+ "@smithy/types": "^1.1.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/endpoint-cache": {
+ "version": "3.310.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.310.0.tgz",
+ "integrity": "sha512-y3wipforet41EDTI0vnzxILqwAGll1KfI5qcdX9pXF/WF1f+3frcOtPiWtQEZQpy4czRogKm3BHo70QBYAZxlQ==",
+ "dependencies": {
+ "mnemonist": "0.38.3",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-endpoint-discovery": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.369.0.tgz",
+ "integrity": "sha512-iNxD1ae8YIA853HBdn76tbYf2OLMJXGsRzlEDxTtnT8qWCiCAWuzsWclG/T88Cj0oYqbs1DHtDPH+Q8Eqomv3w==",
+ "dependencies": {
+ "@aws-sdk/endpoint-cache": "3.310.0",
+ "@aws-sdk/types": "3.369.0",
+ "@smithy/protocol-http": "^1.1.0",
+ "@smithy/types": "^1.1.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-host-header": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.369.0.tgz",
+ "integrity": "sha512-ysbur68WHY7RYpGfth1Iu0+S03nSCLtIHJ+CDVYcVcyvYxaAv6y3gvfrkH9oL220uX75UVLj3tCKgAaLUBy5uA==",
+ "dependencies": {
+ "@aws-sdk/types": "3.369.0",
+ "@smithy/protocol-http": "^1.1.0",
+ "@smithy/types": "^1.1.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-logger": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.369.0.tgz",
+ "integrity": "sha512-mp4gVRaFRRX+LEDEIlPxHOI/+k1jPPp0tuKyoyNZQS8IPOL+6bqFdPan03hkTjujeyaZOyRjpaXXat6k1HkHhw==",
+ "dependencies": {
+ "@aws-sdk/types": "3.369.0",
+ "@smithy/types": "^1.1.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-recursion-detection": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.369.0.tgz",
+ "integrity": "sha512-V7TNhHRTwiKlVXiaW2CYGcm3vObWdG5zU0SN7ZxHDT27eTRYL8ncVpDnQZ65HfekXL8T9llVibBTYYvZrxLJ1g==",
+ "dependencies": {
+ "@aws-sdk/types": "3.369.0",
+ "@smithy/protocol-http": "^1.1.0",
+ "@smithy/types": "^1.1.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-sdk-ec2": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-ec2/-/middleware-sdk-ec2-3.369.0.tgz",
+ "integrity": "sha512-fHLEHLhA3N2/37kxsrzKfq8+gcX+J+JmY36hPn3yW+rJD6fK7c7U3iZ5gADPDlT3J/U7hwk9I4qXJc09WrMgzw==",
+ "dependencies": {
+ "@aws-sdk/types": "3.369.0",
+ "@aws-sdk/util-format-url": "3.369.0",
+ "@smithy/middleware-endpoint": "^1.0.1",
+ "@smithy/protocol-http": "^1.1.0",
+ "@smithy/signature-v4": "^1.0.1",
+ "@smithy/smithy-client": "^1.0.3",
+ "@smithy/types": "^1.1.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-sdk-rds": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-rds/-/middleware-sdk-rds-3.369.0.tgz",
+ "integrity": "sha512-NeET6FUSH7uxpYk5MRs++4MY02FoOdFlbsYSAvsFx01V+hpoVQ5nvePqvvKee+2qyyq+eB1o9MuWksM3e019eQ==",
+ "dependencies": {
+ "@aws-sdk/types": "3.369.0",
+ "@aws-sdk/util-format-url": "3.369.0",
+ "@smithy/middleware-endpoint": "^1.0.1",
+ "@smithy/protocol-http": "^1.1.0",
+ "@smithy/signature-v4": "^1.0.1",
+ "@smithy/types": "^1.1.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-sdk-sts": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.369.0.tgz",
+ "integrity": "sha512-Igizyt7TWy8kTitvE6o7R1Cfa4qLqijS/WxqT1cnHscQyZFFiIJVNypWeV4V19DZ9Msb/feAQdc8EWgHvZvYGA==",
+ "dependencies": {
+ "@aws-sdk/middleware-signing": "3.369.0",
+ "@aws-sdk/types": "3.369.0",
+ "@smithy/types": "^1.1.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-signing": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.369.0.tgz",
+ "integrity": "sha512-55qihn+9/zjsHUNvEgc4OUWQBxVlKW9C+whVhdy8H8olwAnfOH1ui9xXQ+SAyBCD9ck3vAY89VmBeQQQGZVVQw==",
+ "dependencies": {
+ "@aws-sdk/types": "3.369.0",
+ "@smithy/property-provider": "^1.0.1",
+ "@smithy/protocol-http": "^1.1.0",
+ "@smithy/signature-v4": "^1.0.1",
+ "@smithy/types": "^1.1.0",
+ "@smithy/util-middleware": "^1.0.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-user-agent": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.369.0.tgz",
+ "integrity": "sha512-a7Wb3s0y+blGF654GZv3nI3ZMRARAGH7iQrF2gWGtb2Qq0f3TQGHmpoHddWObYxiFWYzdXdTC3kbsAW1zRwEAA==",
+ "dependencies": {
+ "@aws-sdk/types": "3.369.0",
+ "@aws-sdk/util-endpoints": "3.369.0",
+ "@smithy/protocol-http": "^1.1.0",
+ "@smithy/types": "^1.1.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/token-providers": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.369.0.tgz",
+ "integrity": "sha512-xIz8KbF4RMlMq0aAJbVocLB03OiqJIU5RLy+2t+bKMQ60fV4bnVINH5GxAMiFXiBIQVqfehFJlxJACtEphqQwA==",
+ "dependencies": {
+ "@aws-sdk/client-sso-oidc": "3.369.0",
+ "@aws-sdk/types": "3.369.0",
+ "@smithy/property-provider": "^1.0.1",
+ "@smithy/shared-ini-file-loader": "^1.0.1",
+ "@smithy/types": "^1.1.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/types": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.369.0.tgz",
+ "integrity": "sha512-0LgII+RatF2OEFaFQcNyX72py4ZgWz+/JAv++PXv0gkIaTRnsJbSveQArNynEK+aAc/rZKWJgBvwT4FvLM2vgA==",
+ "dependencies": {
+ "@smithy/types": "1.1.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/types/node_modules/@smithy/types": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@smithy/types/-/types-1.1.0.tgz",
+ "integrity": "sha512-KzmvisMmuwD2jZXuC9e65JrgsZM97y5NpDU7g347oB+Q+xQLU6hQZ5zFNNbEfwwOJHoOvEVTna+dk1h/lW7alw==",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-endpoints": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.369.0.tgz",
+ "integrity": "sha512-dkzhhMIvQRsgdomHi8fmgQ3df2cS1jeWAUIPjxV4lBikcvcF2U0CtvH9QYyMpluSNP1IYcEuONe8wfZGSrNjdg==",
+ "dependencies": {
+ "@aws-sdk/types": "3.369.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-format-url": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.369.0.tgz",
+ "integrity": "sha512-rvaUd1EBt8tqqrcp+3Uo4nQTpLkExZPLQluI3sbUlbolGRanTm960Lc2kA5n7pO0zpaobo6Nfycj+FL2i0VIIg==",
+ "dependencies": {
+ "@aws-sdk/types": "3.369.0",
+ "@smithy/querystring-builder": "^1.0.1",
+ "@smithy/types": "^1.1.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-locate-window": {
+ "version": "3.310.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz",
+ "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-user-agent-browser": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.369.0.tgz",
+ "integrity": "sha512-wrF0CqnfFac4sYr8jLZXz7B5NPxdW4GettH07Sl3ihO2aXsTvZ0RoyqzwF7Eve8ihbK0vCKt1S3/vZTOLw8sCg==",
+ "dependencies": {
+ "@aws-sdk/types": "3.369.0",
+ "@smithy/types": "^1.1.0",
+ "bowser": "^2.11.0",
+ "tslib": "^2.5.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-user-agent-node": {
+ "version": "3.369.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.369.0.tgz",
+ "integrity": "sha512-RkiGyWp+YUlK4njsvqD7S08aihEW8aMNrT5OXmLGdukEUGWMAyvIcq4XS8MxA02GRPUxTUNInLltXwc1AaDpCw==",
+ "dependencies": {
+ "@aws-sdk/types": "3.369.0",
+ "@smithy/node-config-provider": "^1.0.1",
+ "@smithy/types": "^1.1.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "aws-crt": ">=1.0.0"
+ },
+ "peerDependenciesMeta": {
+ "aws-crt": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@aws-sdk/util-utf8-browser": {
+ "version": "3.259.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz",
+ "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==",
+ "dependencies": {
+ "tslib": "^2.3.1"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/aws-lambda-dynamodb": {
+ "version": "2.41.0",
+ "resolved": "https://registry.npmjs.org/@aws-solutions-constructs/aws-lambda-dynamodb/-/aws-lambda-dynamodb-2.41.0.tgz",
+ "integrity": "sha512-j95KazBemUur1/iioSH2CpYF7rCzHhNpMQPd0P4lnYFoip0x84Bctktk3+QhucNUwMN4KsTu2EYKDPM3RYgbiQ==",
+ "dependencies": {
+ "@aws-solutions-constructs/core": "2.41.0"
+ },
+ "peerDependencies": {
+ "@aws-solutions-constructs/core": "2.41.0",
+ "aws-cdk-lib": "^2.82.0",
+ "constructs": "^10.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core": {
+ "version": "2.41.0",
+ "resolved": "https://registry.npmjs.org/@aws-solutions-constructs/core/-/core-2.41.0.tgz",
+ "integrity": "sha512-J8qjzH3TKGbwN0mg/OhQSAKpKzGPHZjIKK1UBCJxXuF9oxOjIcPZphZSLOH8Lvz/naO3G5CZhvZLFKbqI9br2A==",
+ "bundleDependencies": [
+ "deepmerge",
+ "npmlog",
+ "deep-diff"
+ ],
+ "dependencies": {
+ "deep-diff": "^1.0.2",
+ "deepmerge": "^4.0.0",
+ "npmlog": "^4.1.2"
+ },
+ "peerDependencies": {
+ "aws-cdk-lib": "^2.82.0",
+ "constructs": "^10.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/ansi-regex": {
+ "version": "2.1.1",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/aproba": {
+ "version": "1.2.0",
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/are-we-there-yet": {
+ "version": "1.1.7",
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/code-point-at": {
+ "version": "1.1.0",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/console-control-strings": {
+ "version": "1.1.0",
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/core-util-is": {
+ "version": "1.0.3",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/deep-diff": {
+ "version": "1.0.2",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/deepmerge": {
+ "version": "4.3.1",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/delegates": {
+ "version": "1.0.0",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/gauge": {
+ "version": "2.7.4",
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/has-unicode": {
+ "version": "2.0.1",
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/inherits": {
+ "version": "2.0.4",
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "number-is-nan": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/isarray": {
+ "version": "1.0.0",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/npmlog": {
+ "version": "4.1.2",
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/number-is-nan": {
+ "version": "1.0.1",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/object-assign": {
+ "version": "4.1.1",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/process-nextick-args": {
+ "version": "2.0.1",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/set-blocking": {
+ "version": "2.0.0",
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/signal-exit": {
+ "version": "3.0.7",
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/string-width": {
+ "version": "1.0.2",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/strip-ansi": {
+ "version": "3.0.1",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/wide-align": {
+ "version": "1.1.5",
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^1.0.2 || 2 || 3 || 4"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/wide-align/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/wide-align/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/wide-align/node_modules/string-width": {
+ "version": "4.2.3",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@aws-solutions-constructs/core/node_modules/wide-align/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz",
+ "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/highlight": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.22.6",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.6.tgz",
+ "integrity": "sha512-29tfsWTq2Ftu7MXmimyC0C5FDZv5DYxOZkh3XD3+QW4V/BYuv/LyEsjj3c0hqedEaDt6DBfDvexMKU8YevdqFg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.22.8",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.8.tgz",
+ "integrity": "sha512-75+KxFB4CZqYRXjx4NlR4J7yGvKumBuZTmV4NV6v09dVXXkuYVYLT68N6HCzLvfJ+fWCxQsntNzKwwIXL4bHnw==",
+ "dev": true,
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.22.5",
+ "@babel/generator": "^7.22.7",
+ "@babel/helper-compilation-targets": "^7.22.6",
+ "@babel/helper-module-transforms": "^7.22.5",
+ "@babel/helpers": "^7.22.6",
+ "@babel/parser": "^7.22.7",
+ "@babel/template": "^7.22.5",
+ "@babel/traverse": "^7.22.8",
+ "@babel/types": "^7.22.5",
+ "@nicolo-ribaudo/semver-v6": "^6.3.3",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.2"
+ },
+ "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.22.7",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.7.tgz",
+ "integrity": "sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.22.5",
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "@jridgewell/trace-mapping": "^0.3.17",
+ "jsesc": "^2.5.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/generator/node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/generator/node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.14",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+ "dev": true
+ },
+ "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.18",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz",
+ "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "3.1.0",
+ "@jridgewell/sourcemap-codec": "1.4.14"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.22.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.6.tgz",
+ "integrity": "sha512-534sYEqWD9VfUm3IPn2SLcH4Q3P86XL+QvqdC7ZsFrzyyPF3T4XGiVghF6PTYNdWg6pXuoqXxNQAhbYeEInTzA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.22.6",
+ "@babel/helper-validator-option": "^7.22.5",
+ "@nicolo-ribaudo/semver-v6": "^6.3.3",
+ "browserslist": "^4.21.9",
+ "lru-cache": "^5.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-environment-visitor": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
+ "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-function-name": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz",
+ "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.22.5",
+ "@babel/types": "^7.22.5"
+ },
+ "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.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz",
+ "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz",
+ "integrity": "sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-module-imports": "^7.22.5",
+ "@babel/helper-simple-access": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.5",
+ "@babel/template": "^7.22.5",
+ "@babel/traverse": "^7.22.5",
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.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.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz",
+ "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz",
+ "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.22.6",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz",
+ "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.22.5",
+ "@babel/traverse": "^7.22.6",
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz",
+ "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.22.5",
+ "chalk": "^2.0.0",
+ "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.22.7",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz",
+ "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==",
+ "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.5",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz",
+ "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.22.5",
+ "@babel/parser": "^7.22.5",
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.22.8",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz",
+ "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.22.5",
+ "@babel/generator": "^7.22.7",
+ "@babel/helper-environment-visitor": "^7.22.5",
+ "@babel/helper-function-name": "^7.22.5",
+ "@babel/helper-hoist-variables": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "@babel/parser": "^7.22.7",
+ "@babel/types": "^7.22.5",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse/node_modules/globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz",
+ "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.22.5",
+ "@babel/helper-validator-identifier": "^7.22.5",
+ "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/@colors/colors": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
+ "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">=0.1.90"
+ }
+ },
+ "node_modules/@cspotcode/source-map-support": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
+ "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/trace-mapping": "0.3.9"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.18.11",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.11.tgz",
+ "integrity": "sha512-q4qlUf5ucwbUJZXF5tEQ8LF7y0Nk4P58hOsGk3ucY0oCwgQqAnqXVbUuahCddVHfrxmpyewRpiTHwVHIETYu7Q==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.18.11",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.11.tgz",
+ "integrity": "sha512-snieiq75Z1z5LJX9cduSAjUr7vEI1OdlzFPMw0HH5YI7qQHDd3qs+WZoMrWYDsfRJSq36lIA6mfZBkvL46KoIw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.18.11",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.11.tgz",
+ "integrity": "sha512-iPuoxQEV34+hTF6FT7om+Qwziv1U519lEOvekXO9zaMMlT9+XneAhKL32DW3H7okrCOBQ44BMihE8dclbZtTuw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.18.11",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.11.tgz",
+ "integrity": "sha512-Gm0QkI3k402OpfMKyQEEMG0RuW2LQsSmI6OeO4El2ojJMoF5NLYb3qMIjvbG/lbMeLOGiW6ooU8xqc+S0fgz2w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.18.11",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.11.tgz",
+ "integrity": "sha512-N15Vzy0YNHu6cfyDOjiyfJlRJCB/ngKOAvoBf1qybG3eOq0SL2Lutzz9N7DYUbb7Q23XtHPn6lMDF6uWbGv9Fw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.18.11",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.11.tgz",
+ "integrity": "sha512-atEyuq6a3omEY5qAh5jIORWk8MzFnCpSTUruBgeyN9jZq1K/QI9uke0ATi3MHu4L8c59CnIi4+1jDKMuqmR71A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.18.11",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.11.tgz",
+ "integrity": "sha512-XtuPrEfBj/YYYnAAB7KcorzzpGTvOr/dTtXPGesRfmflqhA4LMF0Gh/n5+a9JBzPuJ+CGk17CA++Hmr1F/gI0Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.18.11",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.11.tgz",
+ "integrity": "sha512-Idipz+Taso/toi2ETugShXjQ3S59b6m62KmLHkJlSq/cBejixmIydqrtM2XTvNCywFl3VC7SreSf6NV0i6sRyg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.18.11",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.11.tgz",
+ "integrity": "sha512-c6Vh2WS9VFKxKZ2TvJdA7gdy0n6eSy+yunBvv4aqNCEhSWVor1TU43wNRp2YLO9Vng2G+W94aRz+ILDSwAiYog==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.18.11",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.11.tgz",
+ "integrity": "sha512-S3hkIF6KUqRh9n1Q0dSyYcWmcVa9Cg+mSoZEfFuzoYXXsk6196qndrM+ZiHNwpZKi3XOXpShZZ+9dfN5ykqjjw==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.18.11",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.11.tgz",
+ "integrity": "sha512-MRESANOoObQINBA+RMZW+Z0TJWpibtE7cPFnahzyQHDCA9X9LOmGh68MVimZlM9J8n5Ia8lU773te6O3ILW8kw==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.18.11",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.11.tgz",
+ "integrity": "sha512-qVyPIZrXNMOLYegtD1u8EBccCrBVshxMrn5MkuFc3mEVsw7CCQHaqZ4jm9hbn4gWY95XFnb7i4SsT3eflxZsUg==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.18.11",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.11.tgz",
+ "integrity": "sha512-T3yd8vJXfPirZaUOoA9D2ZjxZX4Gr3QuC3GztBJA6PklLotc/7sXTOuuRkhE9W/5JvJP/K9b99ayPNAD+R+4qQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.18.11",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.11.tgz",
+ "integrity": "sha512-evUoRPWiwuFk++snjH9e2cAjF5VVSTj+Dnf+rkO/Q20tRqv+644279TZlPK8nUGunjPAtQRCj1jQkDAvL6rm2w==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.18.11",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.11.tgz",
+ "integrity": "sha512-/SlRJ15XR6i93gRWquRxYCfhTeC5PdqEapKoLbX63PLCmAkXZHY2uQm2l9bN0oPHBsOw2IswRZctMYS0MijFcg==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.18.11",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.11.tgz",
+ "integrity": "sha512-xcncej+wF16WEmIwPtCHi0qmx1FweBqgsRtEL1mSHLFR6/mb3GEZfLQnx+pUDfRDEM4DQF8dpXIW7eDOZl1IbA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.18.11",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.11.tgz",
+ "integrity": "sha512-aSjMHj/F7BuS1CptSXNg6S3M4F3bLp5wfFPIJM+Km2NfIVfFKhdmfHF9frhiCLIGVzDziggqWll0B+9AUbud/Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.18.11",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.11.tgz",
+ "integrity": "sha512-tNBq+6XIBZtht0xJGv7IBB5XaSyvYPCm1PxJ33zLQONdZoLVM0bgGqUrXnJyiEguD9LU4AHiu+GCXy/Hm9LsdQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.18.11",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.11.tgz",
+ "integrity": "sha512-kxfbDOrH4dHuAAOhr7D7EqaYf+W45LsAOOhAet99EyuxxQmjbk8M9N4ezHcEiCYPaiW8Dj3K26Z2V17Gt6p3ng==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.18.11",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.11.tgz",
+ "integrity": "sha512-Sh0dDRyk1Xi348idbal7lZyfSkjhJsdFeuC13zqdipsvMetlGiFQNdO+Yfp6f6B4FbyQm7qsk16yaZk25LChzg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.18.11",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.11.tgz",
+ "integrity": "sha512-o9JUIKF1j0rqJTFbIoF4bXj6rvrTZYOrfRcGyL0Vm5uJ/j5CkBD/51tpdxe9lXEDouhRgdr/BYzUrDOvrWwJpg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.18.11",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.11.tgz",
+ "integrity": "sha512-rQI4cjLHd2hGsM1LqgDI7oOCYbQ6IBOVsX9ejuRMSze0GqXUG2ekwiKkiBU1pRGSeCqFFHxTrcEydB2Hyoz9CA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
+ "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.5.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz",
+ "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz",
+ "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.6.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "8.44.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz",
+ "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
+ "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==",
+ "dev": true,
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^1.2.1",
+ "debug": "^4.1.1",
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
+ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
+ "dev": true
+ },
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true
+ },
+ "node_modules/@isaacs/cliui/node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dev": true,
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "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/load-nyc-config/node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
+ "version": "3.14.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/@istanbuljs/load-nyc-config/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "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.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.1.tgz",
+ "integrity": "sha512-Aj772AYgwTSr5w8qnyoJ0eDYvN6bMsH3ORH1ivMotrInHLKdUz6BDlaEXHdM6kODaBIkNIyQGzsMvRdOv7VG7Q==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.1",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "jest-message-util": "^29.6.1",
+ "jest-util": "^29.6.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/core": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.1.tgz",
+ "integrity": "sha512-CcowHypRSm5oYQ1obz1wfvkjZZ2qoQlrKKvlfPwh5jUXVU12TWr2qMeH8chLMuTFzHh5a1g2yaqlqDICbr+ukQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/console": "^29.6.1",
+ "@jest/reporters": "^29.6.1",
+ "@jest/test-result": "^29.6.1",
+ "@jest/transform": "^29.6.1",
+ "@jest/types": "^29.6.1",
+ "@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.5.0",
+ "jest-config": "^29.6.1",
+ "jest-haste-map": "^29.6.1",
+ "jest-message-util": "^29.6.1",
+ "jest-regex-util": "^29.4.3",
+ "jest-resolve": "^29.6.1",
+ "jest-resolve-dependencies": "^29.6.1",
+ "jest-runner": "^29.6.1",
+ "jest-runtime": "^29.6.1",
+ "jest-snapshot": "^29.6.1",
+ "jest-util": "^29.6.1",
+ "jest-validate": "^29.6.1",
+ "jest-watcher": "^29.6.1",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.6.1",
+ "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/environment": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.1.tgz",
+ "integrity": "sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A==",
+ "dev": true,
+ "dependencies": {
+ "@jest/fake-timers": "^29.6.1",
+ "@jest/types": "^29.6.1",
+ "@types/node": "*",
+ "jest-mock": "^29.6.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.1.tgz",
+ "integrity": "sha512-N5xlPrAYaRNyFgVf2s9Uyyvr795jnB6rObuPx4QFvNJz8aAjpZUDfO4bh5G/xuplMID8PrnuF1+SfSyDxhsgYg==",
+ "dev": true,
+ "dependencies": {
+ "expect": "^29.6.1",
+ "jest-snapshot": "^29.6.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect-utils": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.1.tgz",
+ "integrity": "sha512-o319vIf5pEMx0LmzSxxkYYxo4wrRLKHq9dP1yJU7FoPTB0LfAKSz8SWD6D/6U3v/O52t9cF5t+MeJiRsfk7zMw==",
+ "dev": true,
+ "dependencies": {
+ "jest-get-type": "^29.4.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/fake-timers": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.1.tgz",
+ "integrity": "sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.1",
+ "@sinonjs/fake-timers": "^10.0.2",
+ "@types/node": "*",
+ "jest-message-util": "^29.6.1",
+ "jest-mock": "^29.6.1",
+ "jest-util": "^29.6.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/globals": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.1.tgz",
+ "integrity": "sha512-2VjpaGy78JY9n9370H8zGRCFbYVWwjY6RdDMhoJHa1sYfwe6XM/azGN0SjY8kk7BOZApIejQ1BFPyH7FPG0w3A==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^29.6.1",
+ "@jest/expect": "^29.6.1",
+ "@jest/types": "^29.6.1",
+ "jest-mock": "^29.6.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/reporters": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.1.tgz",
+ "integrity": "sha512-9zuaI9QKr9JnoZtFQlw4GREQbxgmNYXU6QuWtmuODvk5nvPUeBYapVR/VYMyi2WSx3jXTLJTJji8rN6+Cm4+FA==",
+ "dev": true,
+ "dependencies": {
+ "@bcoe/v8-coverage": "^0.2.3",
+ "@jest/console": "^29.6.1",
+ "@jest/test-result": "^29.6.1",
+ "@jest/transform": "^29.6.1",
+ "@jest/types": "^29.6.1",
+ "@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": "^5.1.0",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.0",
+ "istanbul-reports": "^3.1.3",
+ "jest-message-util": "^29.6.1",
+ "jest-util": "^29.6.1",
+ "jest-worker": "^29.6.1",
+ "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/reporters/node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jest/reporters/node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.14",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+ "dev": true
+ },
+ "node_modules/@jest/reporters/node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.18",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz",
+ "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "3.1.0",
+ "@jridgewell/sourcemap-codec": "1.4.14"
+ }
+ },
+ "node_modules/@jest/schemas": {
+ "version": "29.6.0",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz",
+ "integrity": "sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==",
+ "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.0",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz",
+ "integrity": "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==",
+ "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/source-map/node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jest/source-map/node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.14",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+ "dev": true
+ },
+ "node_modules/@jest/source-map/node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.18",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz",
+ "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "3.1.0",
+ "@jridgewell/sourcemap-codec": "1.4.14"
+ }
+ },
+ "node_modules/@jest/test-result": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.1.tgz",
+ "integrity": "sha512-Ynr13ZRcpX6INak0TPUukU8GWRfm/vAytE3JbJNGAvINySWYdfE7dGZMbk36oVuK4CigpbhMn8eg1dixZ7ZJOw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/console": "^29.6.1",
+ "@jest/types": "^29.6.1",
+ "@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.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.1.tgz",
+ "integrity": "sha512-oBkC36PCDf/wb6dWeQIhaviU0l5u6VCsXa119yqdUosYAt7/FbQU2M2UoziO3igj/HBDEgp57ONQ3fm0v9uyyg==",
+ "dev": true,
+ "dependencies": {
+ "@jest/test-result": "^29.6.1",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.6.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/transform": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.1.tgz",
+ "integrity": "sha512-URnTneIU3ZjRSaf906cvf6Hpox3hIeJXRnz3VDSw5/X93gR8ycdfSIEy19FlVx8NFmpN7fe3Gb1xF+NjXaQLWg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/types": "^29.6.1",
+ "@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.6.1",
+ "jest-regex-util": "^29.4.3",
+ "jest-util": "^29.6.1",
+ "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/transform/node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jest/transform/node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.14",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+ "dev": true
+ },
+ "node_modules/@jest/transform/node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.18",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz",
+ "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "3.1.0",
+ "@jridgewell/sourcemap-codec": "1.4.14"
+ }
+ },
+ "node_modules/@jest/types": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz",
+ "integrity": "sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.0",
+ "@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.9",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
+ "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "node_modules/@nicolo-ribaudo/semver-v6": {
+ "version": "6.3.3",
+ "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/semver-v6/-/semver-v6-6.3.3.tgz",
+ "integrity": "sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@npmcli/fs": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz",
+ "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@npmcli/git": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.1.0.tgz",
+ "integrity": "sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==",
+ "dev": true,
+ "dependencies": {
+ "@npmcli/promise-spawn": "^6.0.0",
+ "lru-cache": "^7.4.4",
+ "npm-pick-manifest": "^8.0.0",
+ "proc-log": "^3.0.0",
+ "promise-inflight": "^1.0.1",
+ "promise-retry": "^2.0.1",
+ "semver": "^7.3.5",
+ "which": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@npmcli/git/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@npmcli/git/node_modules/which": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz",
+ "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/which.js"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@npmcli/installed-package-contents": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz",
+ "integrity": "sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==",
+ "dev": true,
+ "dependencies": {
+ "npm-bundled": "^3.0.0",
+ "npm-normalize-package-bin": "^3.0.0"
+ },
+ "bin": {
+ "installed-package-contents": "lib/index.js"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@npmcli/node-gyp": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz",
+ "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==",
+ "dev": true,
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@npmcli/promise-spawn": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz",
+ "integrity": "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==",
+ "dev": true,
+ "dependencies": {
+ "which": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@npmcli/promise-spawn/node_modules/which": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz",
+ "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/which.js"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@npmcli/run-script": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-6.0.2.tgz",
+ "integrity": "sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==",
+ "dev": true,
+ "dependencies": {
+ "@npmcli/node-gyp": "^3.0.0",
+ "@npmcli/promise-spawn": "^6.0.0",
+ "node-gyp": "^9.0.0",
+ "read-package-json-fast": "^3.0.0",
+ "which": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@npmcli/run-script/node_modules/which": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz",
+ "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/which.js"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@pkgr/utils": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz",
+ "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "fast-glob": "^3.3.0",
+ "is-glob": "^4.0.3",
+ "open": "^9.1.0",
+ "picocolors": "^1.0.0",
+ "tslib": "^2.6.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
+ "node_modules/@pnpm/config.env-replace": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz",
+ "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.22.0"
+ }
+ },
+ "node_modules/@pnpm/network.ca-file": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz",
+ "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "4.2.10"
+ },
+ "engines": {
+ "node": ">=12.22.0"
+ }
+ },
+ "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "node_modules/@pnpm/npm-conf": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz",
+ "integrity": "sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==",
+ "dev": true,
+ "dependencies": {
+ "@pnpm/config.env-replace": "^1.1.0",
+ "@pnpm/network.ca-file": "^1.0.1",
+ "config-chain": "^1.1.11"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@sigstore/protobuf-specs": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.1.0.tgz",
+ "integrity": "sha512-a31EnjuIDSX8IXBUib3cYLDRlPMU36AWX4xS8ysLaNu4ZzUesDiPt83pgrW2X1YLMe5L2HbDyaKK5BrL4cNKaQ==",
+ "dev": true,
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@sigstore/tuf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-1.0.2.tgz",
+ "integrity": "sha512-vjwcYePJzM01Ha6oWWZ9gNcdIgnzyFxfqfWzph483DPJTH8Tb7f7bQRRll3CYVkyH56j0AgcPAcl6Vg95DPF+Q==",
+ "dev": true,
+ "dependencies": {
+ "@sigstore/protobuf-specs": "^0.1.0",
+ "tuf-js": "^1.1.7"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@sinclair/typebox": {
+ "version": "0.27.8",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
+ "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
+ "dev": true
+ },
+ "node_modules/@sindresorhus/is": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.4.1.tgz",
+ "integrity": "sha512-axlrvsHlHlFmKKMEg4VyvMzFr93JWJj4eIfXY1STVuO2fsImCa7ncaiG5gC8HKOX590AW5RtRsC41/B+OfrSqw==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/is?sponsor=1"
+ }
+ },
+ "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/@smithy/abort-controller": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-1.0.2.tgz",
+ "integrity": "sha512-tb2h0b+JvMee+eAxTmhnyqyNk51UXIK949HnE14lFeezKsVJTB30maan+CO2IMwnig2wVYQH84B5qk6ylmKCuA==",
+ "dependencies": {
+ "@smithy/types": "^1.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/config-resolver": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-1.0.2.tgz",
+ "integrity": "sha512-8Bk7CgnVKg1dn5TgnjwPz2ebhxeR7CjGs5yhVYH3S8x0q8yPZZVWwpRIglwXaf5AZBzJlNO1lh+lUhMf2e73zQ==",
+ "dependencies": {
+ "@smithy/types": "^1.1.1",
+ "@smithy/util-config-provider": "^1.0.2",
+ "@smithy/util-middleware": "^1.0.2",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/credential-provider-imds": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-1.0.2.tgz",
+ "integrity": "sha512-fLjCya+JOu2gPJpCiwSUyoLvT8JdNJmOaTOkKYBZoGf7CzqR6lluSyI+eboZnl/V0xqcfcqBG4tgqCISmWS3/w==",
+ "dependencies": {
+ "@smithy/node-config-provider": "^1.0.2",
+ "@smithy/property-provider": "^1.0.2",
+ "@smithy/types": "^1.1.1",
+ "@smithy/url-parser": "^1.0.2",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-codec": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-1.0.2.tgz",
+ "integrity": "sha512-eW/XPiLauR1VAgHKxhVvgvHzLROUgTtqat2lgljztbH8uIYWugv7Nz+SgCavB+hWRazv2iYgqrSy74GvxXq/rg==",
+ "dependencies": {
+ "@aws-crypto/crc32": "3.0.0",
+ "@smithy/types": "^1.1.1",
+ "@smithy/util-hex-encoding": "^1.0.2",
+ "tslib": "^2.5.0"
+ }
+ },
+ "node_modules/@smithy/fetch-http-handler": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-1.0.2.tgz",
+ "integrity": "sha512-kynyofLf62LvR8yYphPPdyHb8fWG3LepFinM/vWUTG2Q1pVpmPCM530ppagp3+q2p+7Ox0UvSqldbKqV/d1BpA==",
+ "dependencies": {
+ "@smithy/protocol-http": "^1.1.1",
+ "@smithy/querystring-builder": "^1.0.2",
+ "@smithy/types": "^1.1.1",
+ "@smithy/util-base64": "^1.0.2",
+ "tslib": "^2.5.0"
+ }
+ },
+ "node_modules/@smithy/hash-node": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-1.0.2.tgz",
+ "integrity": "sha512-K6PKhcUNrJXtcesyzhIvNlU7drfIU7u+EMQuGmPw6RQDAg/ufUcfKHz4EcUhFAodUmN+rrejhRG9U6wxjeBOQA==",
+ "dependencies": {
+ "@smithy/types": "^1.1.1",
+ "@smithy/util-buffer-from": "^1.0.2",
+ "@smithy/util-utf8": "^1.0.2",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/invalid-dependency": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-1.0.2.tgz",
+ "integrity": "sha512-B1Y3Tsa6dfC+Vvb+BJMhTHOfFieeYzY9jWQSTR1vMwKkxsymD0OIAnEw8rD/RiDj/4E4RPGFdx9Mdgnyd6Bv5Q==",
+ "dependencies": {
+ "@smithy/types": "^1.1.1",
+ "tslib": "^2.5.0"
+ }
+ },
+ "node_modules/@smithy/is-array-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-1.0.2.tgz",
+ "integrity": "sha512-pkyBnsBRpe+c/6ASavqIMRBdRtZNJEVJOEzhpxZ9JoAXiZYbkfaSMRA/O1dUxGdJ653GHONunnZ4xMo/LJ7utQ==",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-content-length": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-1.0.2.tgz",
+ "integrity": "sha512-pa1/SgGIrSmnEr2c9Apw7CdU4l/HW0fK3+LKFCPDYJrzM0JdYpqjQzgxi31P00eAkL0EFBccpus/p1n2GF9urw==",
+ "dependencies": {
+ "@smithy/protocol-http": "^1.1.1",
+ "@smithy/types": "^1.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-endpoint": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-1.0.3.tgz",
+ "integrity": "sha512-GsWvTXMFjSgl617PCE2km//kIjjtvMRrR2GAuRDIS9sHiLwmkS46VWaVYy+XE7ubEsEtzZ5yK2e8TKDR6Qr5Lw==",
+ "dependencies": {
+ "@smithy/middleware-serde": "^1.0.2",
+ "@smithy/types": "^1.1.1",
+ "@smithy/url-parser": "^1.0.2",
+ "@smithy/util-middleware": "^1.0.2",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-retry": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-1.0.4.tgz",
+ "integrity": "sha512-G7uRXGFL8c3F7APnoIMTtNAHH8vT4F2qVnAWGAZaervjupaUQuRRHYBLYubK0dWzOZz86BtAXKieJ5p+Ni2Xpg==",
+ "dependencies": {
+ "@smithy/protocol-http": "^1.1.1",
+ "@smithy/service-error-classification": "^1.0.3",
+ "@smithy/types": "^1.1.1",
+ "@smithy/util-middleware": "^1.0.2",
+ "@smithy/util-retry": "^1.0.4",
+ "tslib": "^2.5.0",
+ "uuid": "^8.3.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-serde": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-1.0.2.tgz",
+ "integrity": "sha512-T4PcdMZF4xme6koUNfjmSZ1MLi7eoFeYCtodQNQpBNsS77TuJt1A6kt5kP/qxrTvfZHyFlj0AubACoaUqgzPeg==",
+ "dependencies": {
+ "@smithy/types": "^1.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-stack": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-1.0.2.tgz",
+ "integrity": "sha512-H7/uAQEcmO+eDqweEFMJ5YrIpsBwmrXSP6HIIbtxKJSQpAcMGY7KrR2FZgZBi1FMnSUOh+rQrbOyj5HQmSeUBA==",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/node-config-provider": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-1.0.2.tgz",
+ "integrity": "sha512-HU7afWpTToU0wL6KseGDR2zojeyjECQfr8LpjAIeHCYIW7r360ABFf4EaplaJRMVoC3hD9FeltgI3/NtShOqCg==",
+ "dependencies": {
+ "@smithy/property-provider": "^1.0.2",
+ "@smithy/shared-ini-file-loader": "^1.0.2",
+ "@smithy/types": "^1.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/node-http-handler": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-1.0.3.tgz",
+ "integrity": "sha512-PcPUSzTbIb60VCJCiH0PU0E6bwIekttsIEf5Aoo/M0oTfiqsxHTn0Rcij6QoH6qJy6piGKXzLSegspXg5+Kq6g==",
+ "dependencies": {
+ "@smithy/abort-controller": "^1.0.2",
+ "@smithy/protocol-http": "^1.1.1",
+ "@smithy/querystring-builder": "^1.0.2",
+ "@smithy/types": "^1.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/property-provider": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-1.0.2.tgz",
+ "integrity": "sha512-pXDPyzKX8opzt38B205kDgaxda6LHcTfPvTYQZnwP6BAPp1o9puiCPjeUtkKck7Z6IbpXCPUmUQnzkUzWTA42Q==",
+ "dependencies": {
+ "@smithy/types": "^1.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/protocol-http": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-1.1.1.tgz",
+ "integrity": "sha512-mFLFa2sSvlUxm55U7B4YCIsJJIMkA6lHxwwqOaBkral1qxFz97rGffP/mmd4JDuin1EnygiO5eNJGgudiUgmDQ==",
+ "dependencies": {
+ "@smithy/types": "^1.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/querystring-builder": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-1.0.2.tgz",
+ "integrity": "sha512-6P/xANWrtJhMzTPUR87AbXwSBuz1SDHIfL44TFd/GT3hj6rA+IEv7rftEpPjayUiWRocaNnrCPLvmP31mobOyA==",
+ "dependencies": {
+ "@smithy/types": "^1.1.1",
+ "@smithy/util-uri-escape": "^1.0.2",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/querystring-parser": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-1.0.2.tgz",
+ "integrity": "sha512-IWxwxjn+KHWRRRB+K2Ngl+plTwo2WSgc2w+DvLy0DQZJh9UGOpw40d6q97/63GBlXIt4TEt5NbcFrO30CKlrsA==",
+ "dependencies": {
+ "@smithy/types": "^1.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/service-error-classification": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-1.0.3.tgz",
+ "integrity": "sha512-2eglIYqrtcUnuI71yweu7rSfCgt6kVvRVf0C72VUqrd0LrV1M0BM0eYN+nitp2CHPSdmMI96pi+dU9U/UqAMSA==",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/shared-ini-file-loader": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-1.0.2.tgz",
+ "integrity": "sha512-bdQj95VN+lCXki+P3EsDyrkpeLn8xDYiOISBGnUG/AGPYJXN8dmp4EhRRR7XOoLoSs8anZHR4UcGEOzFv2jwGw==",
+ "dependencies": {
+ "@smithy/types": "^1.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/signature-v4": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-1.0.2.tgz",
+ "integrity": "sha512-rpKUhmCuPmpV5dloUkOb9w1oBnJatvKQEjIHGmkjRGZnC3437MTdzWej9TxkagcZ8NRRJavYnEUixzxM1amFig==",
+ "dependencies": {
+ "@smithy/eventstream-codec": "^1.0.2",
+ "@smithy/is-array-buffer": "^1.0.2",
+ "@smithy/types": "^1.1.1",
+ "@smithy/util-hex-encoding": "^1.0.2",
+ "@smithy/util-middleware": "^1.0.2",
+ "@smithy/util-uri-escape": "^1.0.2",
+ "@smithy/util-utf8": "^1.0.2",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/smithy-client": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-1.0.4.tgz",
+ "integrity": "sha512-gpo0Xl5Nyp9sgymEfpt7oa9P2q/GlM3VmQIdm+FeH0QEdYOQx3OtvwVmBYAMv2FIPWxkMZlsPYRTnEiBTK5TYg==",
+ "dependencies": {
+ "@smithy/middleware-stack": "^1.0.2",
+ "@smithy/types": "^1.1.1",
+ "@smithy/util-stream": "^1.0.2",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/types": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@smithy/types/-/types-1.1.1.tgz",
+ "integrity": "sha512-tMpkreknl2gRrniHeBtdgQwaOlo39df8RxSrwsHVNIGXULy5XP6KqgScUw2m12D15wnJCKWxVhCX+wbrBW/y7g==",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/url-parser": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-1.0.2.tgz",
+ "integrity": "sha512-0JRsDMQe53F6EHRWksdcavKDRjyqp8vrjakg8EcCUOa7PaFRRB1SO/xGZdzSlW1RSTWQDEksFMTCEcVEKmAoqA==",
+ "dependencies": {
+ "@smithy/querystring-parser": "^1.0.2",
+ "@smithy/types": "^1.1.1",
+ "tslib": "^2.5.0"
+ }
+ },
+ "node_modules/@smithy/util-base64": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-1.0.2.tgz",
+ "integrity": "sha512-BCm15WILJ3SL93nusoxvJGMVfAMWHZhdeDZPtpAaskozuexd0eF6szdz4kbXaKp38bFCSenA6bkUHqaE3KK0dA==",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^1.0.2",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/util-body-length-browser": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-1.0.2.tgz",
+ "integrity": "sha512-Xh8L06H2anF5BHjSYTg8hx+Itcbf4SQZnVMl4PIkCOsKtneMJoGjPRLy17lEzfoh/GOaa0QxgCP6lRMQWzNl4w==",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ }
+ },
+ "node_modules/@smithy/util-body-length-node": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-1.0.2.tgz",
+ "integrity": "sha512-nXHbZsUtvZeyfL4Ceds9nmy2Uh2AhWXohG4vWHyjSdmT8cXZlJdmJgnH6SJKDjyUecbu+BpKeVvSrA4cWPSOPA==",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/util-buffer-from": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-1.0.2.tgz",
+ "integrity": "sha512-lHAYIyrBO9RANrPvccnPjU03MJnWZ66wWuC5GjWWQVfsmPwU6m00aakZkzHdUT6tGCkGacXSgArP5wgTgA+oCw==",
+ "dependencies": {
+ "@smithy/is-array-buffer": "^1.0.2",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/util-config-provider": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-1.0.2.tgz",
+ "integrity": "sha512-HOdmDm+3HUbuYPBABLLHtn8ittuRyy+BSjKOA169H+EMc+IozipvXDydf+gKBRAxUa4dtKQkLraypwppzi+PRw==",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/util-defaults-mode-browser": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-1.0.2.tgz",
+ "integrity": "sha512-J1u2PO235zxY7dg0+ZqaG96tFg4ehJZ7isGK1pCBEA072qxNPwIpDzUVGnLJkHZvjWEGA8rxIauDtXfB0qxeAg==",
+ "dependencies": {
+ "@smithy/property-provider": "^1.0.2",
+ "@smithy/types": "^1.1.1",
+ "bowser": "^2.11.0",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/@smithy/util-defaults-mode-node": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-1.0.2.tgz",
+ "integrity": "sha512-9/BN63rlIsFStvI+AvljMh873Xw6bbI6b19b+PVYXyycQ2DDQImWcjnzRlHW7eP65CCUNGQ6otDLNdBQCgMXqg==",
+ "dependencies": {
+ "@smithy/config-resolver": "^1.0.2",
+ "@smithy/credential-provider-imds": "^1.0.2",
+ "@smithy/node-config-provider": "^1.0.2",
+ "@smithy/property-provider": "^1.0.2",
+ "@smithy/types": "^1.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/@smithy/util-hex-encoding": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-1.0.2.tgz",
+ "integrity": "sha512-Bxydb5rMJorMV6AuDDMOxro3BMDdIwtbQKHpwvQFASkmr52BnpDsWlxgpJi8Iq7nk1Bt4E40oE1Isy/7ubHGzg==",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/util-middleware": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-1.0.2.tgz",
+ "integrity": "sha512-vtXK7GOR2BoseCX8NCGe9SaiZrm9M2lm/RVexFGyPuafTtry9Vyv7hq/vw8ifd/G/pSJ+msByfJVb1642oQHKw==",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/util-retry": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-1.0.4.tgz",
+ "integrity": "sha512-RnZPVFvRoqdj2EbroDo3OsnnQU8eQ4AlnZTOGusbYKybH3269CFdrZfZJloe60AQjX7di3J6t/79PjwCLO5Khw==",
+ "dependencies": {
+ "@smithy/service-error-classification": "^1.0.3",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@smithy/util-stream": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-1.0.2.tgz",
+ "integrity": "sha512-qyN2M9QFMTz4UCHi6GnBfLOGYKxQZD01Ga6nzaXFFC51HP/QmArU72e4kY50Z/EtW8binPxspP2TAsGbwy9l3A==",
+ "dependencies": {
+ "@smithy/fetch-http-handler": "^1.0.2",
+ "@smithy/node-http-handler": "^1.0.3",
+ "@smithy/types": "^1.1.1",
+ "@smithy/util-base64": "^1.0.2",
+ "@smithy/util-buffer-from": "^1.0.2",
+ "@smithy/util-hex-encoding": "^1.0.2",
+ "@smithy/util-utf8": "^1.0.2",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/util-uri-escape": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-1.0.2.tgz",
+ "integrity": "sha512-k8C0BFNS9HpBMHSgUDnWb1JlCQcFG+PPlVBq9keP4Nfwv6a9Q0yAfASWqUCtzjuMj1hXeLhn/5ADP6JxnID1Pg==",
+ "dependencies": {
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/util-utf8": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-1.0.2.tgz",
+ "integrity": "sha512-V4cyjKfJlARui0dMBfWJMQAmJzoW77i4N3EjkH/bwnE2Ngbl4tqD2Y0C/xzpzY/J1BdxeCKxAebVFk8aFCaSCw==",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^1.0.2",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@smithy/util-waiter": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-1.0.2.tgz",
+ "integrity": "sha512-+jq4/Vd9ejPzR45qwYSePyjQbqYP9QqtyZYsFVyfzRnbGGC0AjswOh7txcxroafuEBExK4qE+L/QZA8wWXsJYw==",
+ "dependencies": {
+ "@smithy/abort-controller": "^1.0.2",
+ "@smithy/types": "^1.1.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@szmarczak/http-timer": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz",
+ "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==",
+ "dev": true,
+ "dependencies": {
+ "defer-to-connect": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=14.16"
+ }
+ },
+ "node_modules/@tootallnate/once": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
+ "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@tsconfig/node10": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
+ "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==",
+ "dev": true
+ },
+ "node_modules/@tsconfig/node12": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
+ "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
+ "dev": true
+ },
+ "node_modules/@tsconfig/node14": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
+ "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
+ "dev": true
+ },
+ "node_modules/@tsconfig/node16": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
+ "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
+ "dev": true
+ },
+ "node_modules/@tufjs/canonical-json": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-1.0.0.tgz",
+ "integrity": "sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==",
+ "dev": true,
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@tufjs/models": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-1.0.4.tgz",
+ "integrity": "sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A==",
+ "dev": true,
+ "dependencies": {
+ "@tufjs/canonical-json": "1.0.0",
+ "minimatch": "^9.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@tufjs/models/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@tufjs/models/node_modules/minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.1",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz",
+ "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==",
+ "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.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz",
+ "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz",
+ "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.20.1",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz",
+ "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.20.7"
+ }
+ },
+ "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/http-cache-semantics": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz",
+ "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==",
+ "dev": true
+ },
+ "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.3",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.3.tgz",
+ "integrity": "sha512-1Nq7YrO/vJE/FYnqYyw0FS8LdrjExSgIiHyKg7xPpn+yi8Q4huZryKnkJatN1ZRH89Kw2v33/8ZMB7DuZeSLlA==",
+ "dev": true,
+ "dependencies": {
+ "expect": "^29.0.0",
+ "pretty-format": "^29.0.0"
+ }
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.12",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz",
+ "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==",
+ "dev": true
+ },
+ "node_modules/@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "dev": true
+ },
+ "node_modules/@types/node": {
+ "version": "18.16.19",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.19.tgz",
+ "integrity": "sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA==",
+ "dev": true
+ },
+ "node_modules/@types/prettier": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz",
+ "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==",
+ "dev": true
+ },
+ "node_modules/@types/semver": {
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz",
+ "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==",
+ "dev": true
+ },
+ "node_modules/@types/stack-utils": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz",
+ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==",
+ "dev": true
+ },
+ "node_modules/@types/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/@typescript-eslint/eslint-plugin": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.0.0.tgz",
+ "integrity": "sha512-xuv6ghKGoiq856Bww/yVYnXGsKa588kY3M0XK7uUW/3fJNNULKRfZfSBkMTSpqGG/8ZCXCadfh8G/z/B4aqS/A==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.5.0",
+ "@typescript-eslint/scope-manager": "6.0.0",
+ "@typescript-eslint/type-utils": "6.0.0",
+ "@typescript-eslint/utils": "6.0.0",
+ "@typescript-eslint/visitor-keys": "6.0.0",
+ "debug": "^4.3.4",
+ "grapheme-splitter": "^1.0.4",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.4",
+ "natural-compare": "^1.4.0",
+ "natural-compare-lite": "^1.4.0",
+ "semver": "^7.5.0",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha",
+ "eslint": "^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.0.0.tgz",
+ "integrity": "sha512-TNaufYSPrr1U8n+3xN+Yp9g31vQDJqhXzzPSHfQDLcaO4tU+mCfODPxCwf4H530zo7aUBE3QIdxCXamEnG04Tg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "6.0.0",
+ "@typescript-eslint/types": "6.0.0",
+ "@typescript-eslint/typescript-estree": "6.0.0",
+ "@typescript-eslint/visitor-keys": "6.0.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.0.0.tgz",
+ "integrity": "sha512-o4q0KHlgCZTqjuaZ25nw5W57NeykZT9LiMEG4do/ovwvOcPnDO1BI5BQdCsUkjxFyrCL0cSzLjvIMfR9uo7cWg==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.0.0",
+ "@typescript-eslint/visitor-keys": "6.0.0"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.0.0.tgz",
+ "integrity": "sha512-ah6LJvLgkoZ/pyJ9GAdFkzeuMZ8goV6BH7eC9FPmojrnX9yNCIsfjB+zYcnex28YO3RFvBkV6rMV6WpIqkPvoQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "6.0.0",
+ "@typescript-eslint/utils": "6.0.0",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.0.0.tgz",
+ "integrity": "sha512-Zk9KDggyZM6tj0AJWYYKgF0yQyrcnievdhG0g5FqyU3Y2DRxJn4yWY21sJC0QKBckbsdKKjYDV2yVrrEvuTgxg==",
+ "dev": true,
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.0.0.tgz",
+ "integrity": "sha512-2zq4O7P6YCQADfmJ5OTDQTP3ktajnXIRrYAtHM9ofto/CJZV3QfJ89GEaM2BNGeSr1KgmBuLhEkz5FBkS2RQhQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.0.0",
+ "@typescript-eslint/visitor-keys": "6.0.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "semver": "^7.5.0",
+ "ts-api-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.0.0.tgz",
+ "integrity": "sha512-SOr6l4NB6HE4H/ktz0JVVWNXqCJTOo/mHnvIte1ZhBQ0Cvd04x5uKZa3zT6tiodL06zf5xxdK8COiDvPnQ27JQ==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.3.0",
+ "@types/json-schema": "^7.0.11",
+ "@types/semver": "^7.3.12",
+ "@typescript-eslint/scope-manager": "6.0.0",
+ "@typescript-eslint/types": "6.0.0",
+ "@typescript-eslint/typescript-estree": "6.0.0",
+ "eslint-scope": "^5.1.1",
+ "semver": "^7.5.0"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.0.0.tgz",
+ "integrity": "sha512-cvJ63l8c0yXdeT5POHpL0Q1cZoRcmRKFCtSjNGJxPkcP571EfZMcNbzWAc7oK3D1dRzm/V5EwtkANTZxqvuuUA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "6.0.0",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^16.0.0 || >=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+ "dev": true
+ },
+ "node_modules/acorn": {
+ "version": "8.10.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
+ "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/acorn-walk": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
+ "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "dev": true,
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/agentkeepalive": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz",
+ "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.1.0",
+ "depd": "^2.0.0",
+ "humanize-ms": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ }
+ },
+ "node_modules/aggregate-error": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+ "dev": true,
+ "dependencies": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-align": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz",
+ "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.1.0"
+ }
+ },
+ "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-escapes/node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "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/aproba": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
+ "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==",
+ "dev": true
+ },
+ "node_modules/are-we-there-yet": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz",
+ "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==",
+ "dev": true,
+ "dependencies": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^3.6.0"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/arg": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
+ "dev": true
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/array-buffer-byte-length": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
+ "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "is-array-buffer": "^3.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-includes": {
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz",
+ "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4",
+ "get-intrinsic": "^1.1.3",
+ "is-string": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/array.prototype.flat": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz",
+ "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flatmap": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz",
+ "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
+ "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/aws-cdk": {
+ "version": "2.87.0",
+ "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.87.0.tgz",
+ "integrity": "sha512-dBm74nl3dMUxoAzgjcfKnzJyoVNIV//B1sqDN11cC3LXEflYapcBxPxZHAyGcRXg5dW3m14dMdKVQfmt4N970g==",
+ "dev": true,
+ "bin": {
+ "cdk": "bin/cdk"
+ },
+ "engines": {
+ "node": ">= 14.15.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "2.3.2"
+ }
+ },
+ "node_modules/aws-cdk-lib": {
+ "version": "2.87.0",
+ "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.87.0.tgz",
+ "integrity": "sha512-9kirXX7L7OP/yGmCbaYlkt5OAtowGiGw0AYFIQvSwvx/UU3aJO5XuDwAgDsvToDkRpBi0yX0bNwqa0DItu+C6A==",
+ "bundleDependencies": [
+ "@balena/dockerignore",
+ "case",
+ "fs-extra",
+ "ignore",
+ "jsonschema",
+ "minimatch",
+ "punycode",
+ "semver",
+ "table",
+ "yaml"
+ ],
+ "dependencies": {
+ "@aws-cdk/asset-awscli-v1": "^2.2.177",
+ "@aws-cdk/asset-kubectl-v20": "^2.1.1",
+ "@aws-cdk/asset-node-proxy-agent-v5": "^2.0.148",
+ "@balena/dockerignore": "^1.0.2",
+ "case": "1.6.3",
+ "fs-extra": "^11.1.1",
+ "ignore": "^5.2.4",
+ "jsonschema": "^1.4.1",
+ "minimatch": "^3.1.2",
+ "punycode": "^2.3.0",
+ "semver": "^7.5.1",
+ "table": "^6.8.1",
+ "yaml": "1.10.2"
+ },
+ "engines": {
+ "node": ">= 14.15.0"
+ },
+ "peerDependencies": {
+ "constructs": "^10.0.0"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/@balena/dockerignore": {
+ "version": "1.0.2",
+ "inBundle": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/aws-cdk-lib/node_modules/ajv": {
+ "version": "8.12.0",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/astral-regex": {
+ "version": "2.0.0",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/balanced-match": {
+ "version": "1.0.2",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/aws-cdk-lib/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/case": {
+ "version": "1.6.3",
+ "inBundle": true,
+ "license": "(MIT OR GPL-3.0-or-later)",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/color-convert": {
+ "version": "2.0.1",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/color-name": {
+ "version": "1.1.4",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/aws-cdk-lib/node_modules/concat-map": {
+ "version": "0.0.1",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/aws-cdk-lib/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/aws-cdk-lib/node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/aws-cdk-lib/node_modules/fs-extra": {
+ "version": "11.1.1",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=14.14"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/aws-cdk-lib/node_modules/ignore": {
+ "version": "5.2.4",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/aws-cdk-lib/node_modules/jsonfile": {
+ "version": "6.1.0",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "universalify": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/jsonschema": {
+ "version": "1.4.1",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/lodash.truncate": {
+ "version": "4.4.2",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/aws-cdk-lib/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/minimatch": {
+ "version": "3.1.2",
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/punycode": {
+ "version": "2.3.0",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/require-from-string": {
+ "version": "2.0.2",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/semver": {
+ "version": "7.5.2",
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/slice-ansi": {
+ "version": "4.0.0",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/string-width": {
+ "version": "4.2.3",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/table": {
+ "version": "6.8.1",
+ "inBundle": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "ajv": "^8.0.1",
+ "lodash.truncate": "^4.4.2",
+ "slice-ansi": "^4.0.0",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/universalify": {
+ "version": "2.0.0",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/uri-js": {
+ "version": "4.4.1",
+ "inBundle": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/aws-cdk-lib/node_modules/yallist": {
+ "version": "4.0.0",
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/aws-cdk-lib/node_modules/yaml": {
+ "version": "1.10.2",
+ "inBundle": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/babel-jest": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.1.tgz",
+ "integrity": "sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A==",
+ "dev": true,
+ "dependencies": {
+ "@jest/transform": "^29.6.1",
+ "@types/babel__core": "^7.1.14",
+ "babel-plugin-istanbul": "^6.1.1",
+ "babel-preset-jest": "^29.5.0",
+ "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-jest-hoist": {
+ "version": "29.5.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz",
+ "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==",
+ "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.5.0",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz",
+ "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==",
+ "dev": true,
+ "dependencies": {
+ "babel-plugin-jest-hoist": "^29.5.0",
+ "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/big-integer": {
+ "version": "1.6.51",
+ "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz",
+ "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/bowser": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz",
+ "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA=="
+ },
+ "node_modules/boxen": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.1.1.tgz",
+ "integrity": "sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==",
+ "dev": true,
+ "dependencies": {
+ "ansi-align": "^3.0.1",
+ "camelcase": "^7.0.1",
+ "chalk": "^5.2.0",
+ "cli-boxes": "^3.0.0",
+ "string-width": "^5.1.2",
+ "type-fest": "^2.13.0",
+ "widest-line": "^4.0.1",
+ "wrap-ansi": "^8.1.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/boxen/node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/boxen/node_modules/camelcase": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz",
+ "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/boxen/node_modules/chalk": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
+ "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
+ "dev": true,
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/boxen/node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true
+ },
+ "node_modules/boxen/node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dev": true,
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/boxen/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/boxen/node_modules/type-fest": {
+ "version": "2.19.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
+ "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/bplist-parser": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz",
+ "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==",
+ "dev": true,
+ "dependencies": {
+ "big-integer": "^1.6.44"
+ },
+ "engines": {
+ "node": ">= 5.10.0"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "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.9",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz",
+ "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==",
+ "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.30001503",
+ "electron-to-chromium": "^1.4.431",
+ "node-releases": "^2.0.12",
+ "update-browserslist-db": "^1.0.11"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/bs-logger": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz",
+ "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==",
+ "dev": true,
+ "dependencies": {
+ "fast-json-stable-stringify": "2.x"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "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=="
+ },
+ "node_modules/builtins": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz",
+ "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^7.0.0"
+ }
+ },
+ "node_modules/bundle-name": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz",
+ "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==",
+ "dev": true,
+ "dependencies": {
+ "run-applescript": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cacache": {
+ "version": "17.1.3",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.3.tgz",
+ "integrity": "sha512-jAdjGxmPxZh0IipMdR7fK/4sDSrHMLUV0+GvVUsjwyGNKHsh79kW/otg+GkbXwl6Uzvy9wsvHOX4nUoWldeZMg==",
+ "dev": true,
+ "dependencies": {
+ "@npmcli/fs": "^3.1.0",
+ "fs-minipass": "^3.0.0",
+ "glob": "^10.2.2",
+ "lru-cache": "^7.7.1",
+ "minipass": "^5.0.0",
+ "minipass-collect": "^1.0.2",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "p-map": "^4.0.0",
+ "ssri": "^10.0.0",
+ "tar": "^6.1.11",
+ "unique-filename": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/cacache/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/cacache/node_modules/glob": {
+ "version": "10.3.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz",
+ "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==",
+ "dev": true,
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^2.0.3",
+ "minimatch": "^9.0.1",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
+ "path-scurry": "^1.10.1"
+ },
+ "bin": {
+ "glob": "dist/cjs/src/bin.js"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/cacache/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/cacache/node_modules/minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/cacheable-lookup": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz",
+ "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.16"
+ }
+ },
+ "node_modules/cacheable-request": {
+ "version": "10.2.12",
+ "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.12.tgz",
+ "integrity": "sha512-qtWGB5kn2OLjx47pYUkWicyOpK1vy9XZhq8yRTXOy+KAmjjESSRLx6SiExnnaGGUP1NM6/vmygMu0fGylNh9tw==",
+ "dev": true,
+ "dependencies": {
+ "@types/http-cache-semantics": "^4.0.1",
+ "get-stream": "^6.0.1",
+ "http-cache-semantics": "^4.1.1",
+ "keyv": "^4.5.2",
+ "mimic-response": "^4.0.0",
+ "normalize-url": "^8.0.0",
+ "responselike": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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.30001515",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001515.tgz",
+ "integrity": "sha512-eEFDwUOZbE24sb+Ecsx3+OvNETqjWIdabMy52oOkIgcUtAsQifjUG9q4U9dgTHJM2mfk4uEPxc0+xuFdJ629QA==",
+ "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/cdk-nag": {
+ "version": "2.27.67",
+ "resolved": "https://registry.npmjs.org/cdk-nag/-/cdk-nag-2.27.67.tgz",
+ "integrity": "sha512-Y2i1R7mqplfxp2RrSvprSQEFBw5K7HwbhQdzrQCEPNVZH25Yk/GIw1qk5tJf38LYSTQh0sAzXdn/n0O9S7y5RQ==",
+ "peerDependencies": {
+ "aws-cdk-lib": "^2.78.0",
+ "constructs": "^10.0.5"
+ }
+ },
+ "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/chownr": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+ "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": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/cli-boxes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz",
+ "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-table3": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz",
+ "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.2.0"
+ },
+ "engines": {
+ "node": "10.* || >= 12.*"
+ },
+ "optionalDependencies": {
+ "@colors/colors": "1.5.0"
+ }
+ },
+ "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/cliui/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/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/color-support": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
+ "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
+ "dev": true,
+ "bin": {
+ "color-support": "bin.js"
+ }
+ },
+ "node_modules/commander": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
+ "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "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/config-chain": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
+ "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
+ "dev": true,
+ "dependencies": {
+ "ini": "^1.3.4",
+ "proto-list": "~1.2.1"
+ }
+ },
+ "node_modules/config-chain/node_modules/ini": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+ "dev": true
+ },
+ "node_modules/configstore": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/configstore/-/configstore-6.0.0.tgz",
+ "integrity": "sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==",
+ "dev": true,
+ "dependencies": {
+ "dot-prop": "^6.0.1",
+ "graceful-fs": "^4.2.6",
+ "unique-string": "^3.0.0",
+ "write-file-atomic": "^3.0.3",
+ "xdg-basedir": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/yeoman/configstore?sponsor=1"
+ }
+ },
+ "node_modules/configstore/node_modules/write-file-atomic": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
+ "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
+ "dev": true,
+ "dependencies": {
+ "imurmurhash": "^0.1.4",
+ "is-typedarray": "^1.0.0",
+ "signal-exit": "^3.0.2",
+ "typedarray-to-buffer": "^3.1.5"
+ }
+ },
+ "node_modules/console-control-strings": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+ "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
+ "dev": true
+ },
+ "node_modules/constructs": {
+ "version": "10.2.69",
+ "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.2.69.tgz",
+ "integrity": "sha512-0AiM/uQe5Uk6JVe/62oolmSN2MjbFQkOlYrM3fFGZLKuT+g7xlAI10EebFhyCcZwI2JAcWuWCmmCAyCothxjuw==",
+ "engines": {
+ "node": ">= 16.14.0"
+ }
+ },
+ "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-require": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
+ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
+ "dev": true
+ },
+ "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/crypto-random-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz",
+ "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/crypto-random-string/node_modules/type-fest": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
+ "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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/decompress-response": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
+ "dev": true,
+ "dependencies": {
+ "mimic-response": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/decompress-response/node_modules/mimic-response": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/dedent": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
+ "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==",
+ "dev": true
+ },
+ "node_modules/deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": 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/default-browser": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz",
+ "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==",
+ "dev": true,
+ "dependencies": {
+ "bundle-name": "^3.0.0",
+ "default-browser-id": "^3.0.0",
+ "execa": "^7.1.1",
+ "titleize": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser-id": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz",
+ "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==",
+ "dev": true,
+ "dependencies": {
+ "bplist-parser": "^0.2.0",
+ "untildify": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser/node_modules/execa": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz",
+ "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.1",
+ "human-signals": "^4.3.0",
+ "is-stream": "^3.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^5.1.0",
+ "onetime": "^6.0.0",
+ "signal-exit": "^3.0.7",
+ "strip-final-newline": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.18.0 || ^16.14.0 || >=18.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/default-browser/node_modules/human-signals": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz",
+ "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.18.0"
+ }
+ },
+ "node_modules/default-browser/node_modules/is-stream": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
+ "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser/node_modules/mimic-fn": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
+ "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser/node_modules/npm-run-path": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
+ "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^4.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser/node_modules/onetime": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
+ "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
+ "dev": true,
+ "dependencies": {
+ "mimic-fn": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser/node_modules/path-key": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
+ "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser/node_modules/strip-final-newline": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
+ "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/defer-to-connect": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
+ "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/define-lazy-prop": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
+ "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz",
+ "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==",
+ "dev": true,
+ "dependencies": {
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/delegates": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
+ "dev": true
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "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": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/diff-sequences": {
+ "version": "29.4.3",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz",
+ "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==",
+ "dev": true,
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/dot-prop": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz",
+ "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==",
+ "dev": true,
+ "dependencies": {
+ "is-obj": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "dev": true
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.4.457",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.457.tgz",
+ "integrity": "sha512-/g3UyNDmDd6ebeWapmAoiyy+Sy2HyJ+/X8KyvNeHfKRFfHaA2W8oF5fxD5F3tjBDcjpwo0iek6YNgxNXDBoEtA==",
+ "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/encoding": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
+ "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "iconv-lite": "^0.6.2"
+ }
+ },
+ "node_modules/env-paths": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
+ "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/err-code": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
+ "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
+ "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/es-abstract": {
+ "version": "1.21.2",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz",
+ "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==",
+ "dev": true,
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.0",
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "es-set-tostringtag": "^2.0.1",
+ "es-to-primitive": "^1.2.1",
+ "function.prototype.name": "^1.1.5",
+ "get-intrinsic": "^1.2.0",
+ "get-symbol-description": "^1.0.0",
+ "globalthis": "^1.0.3",
+ "gopd": "^1.0.1",
+ "has": "^1.0.3",
+ "has-property-descriptors": "^1.0.0",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.5",
+ "is-array-buffer": "^3.0.2",
+ "is-callable": "^1.2.7",
+ "is-negative-zero": "^2.0.2",
+ "is-regex": "^1.1.4",
+ "is-shared-array-buffer": "^1.0.2",
+ "is-string": "^1.0.7",
+ "is-typed-array": "^1.1.10",
+ "is-weakref": "^1.0.2",
+ "object-inspect": "^1.12.3",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.4",
+ "regexp.prototype.flags": "^1.4.3",
+ "safe-regex-test": "^1.0.0",
+ "string.prototype.trim": "^1.2.7",
+ "string.prototype.trimend": "^1.0.6",
+ "string.prototype.trimstart": "^1.0.6",
+ "typed-array-length": "^1.0.4",
+ "unbox-primitive": "^1.0.2",
+ "which-typed-array": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
+ "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.3",
+ "has": "^1.0.3",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-shim-unscopables": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz",
+ "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==",
+ "dev": true,
+ "dependencies": {
+ "has": "^1.0.3"
+ }
+ },
+ "node_modules/es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
+ "dependencies": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.18.11",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.11.tgz",
+ "integrity": "sha512-i8u6mQF0JKJUlGR3OdFLKldJQMMs8OqM9Cc3UCi9XXziJ9WERM5bfkHaEAy0YAvPRMgqSW55W7xYn84XtEFTtA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/android-arm": "0.18.11",
+ "@esbuild/android-arm64": "0.18.11",
+ "@esbuild/android-x64": "0.18.11",
+ "@esbuild/darwin-arm64": "0.18.11",
+ "@esbuild/darwin-x64": "0.18.11",
+ "@esbuild/freebsd-arm64": "0.18.11",
+ "@esbuild/freebsd-x64": "0.18.11",
+ "@esbuild/linux-arm": "0.18.11",
+ "@esbuild/linux-arm64": "0.18.11",
+ "@esbuild/linux-ia32": "0.18.11",
+ "@esbuild/linux-loong64": "0.18.11",
+ "@esbuild/linux-mips64el": "0.18.11",
+ "@esbuild/linux-ppc64": "0.18.11",
+ "@esbuild/linux-riscv64": "0.18.11",
+ "@esbuild/linux-s390x": "0.18.11",
+ "@esbuild/linux-x64": "0.18.11",
+ "@esbuild/netbsd-x64": "0.18.11",
+ "@esbuild/openbsd-x64": "0.18.11",
+ "@esbuild/sunos-x64": "0.18.11",
+ "@esbuild/win32-arm64": "0.18.11",
+ "@esbuild/win32-ia32": "0.18.11",
+ "@esbuild/win32-x64": "0.18.11"
+ }
+ },
+ "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-goat": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-4.0.0.tgz",
+ "integrity": "sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.44.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.44.0.tgz",
+ "integrity": "sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.4.0",
+ "@eslint/eslintrc": "^2.1.0",
+ "@eslint/js": "8.44.0",
+ "@humanwhocodes/config-array": "^0.11.10",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "ajv": "^6.10.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.0",
+ "eslint-visitor-keys": "^3.4.1",
+ "espree": "^9.6.0",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "strip-json-comments": "^3.1.0",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-config-prettier": {
+ "version": "8.8.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz",
+ "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==",
+ "dev": true,
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint-import-resolver-node": {
+ "version": "0.3.7",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz",
+ "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^3.2.7",
+ "is-core-module": "^2.11.0",
+ "resolve": "^1.22.1"
+ }
+ },
+ "node_modules/eslint-import-resolver-node/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-module-utils": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz",
+ "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^3.2.7"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependenciesMeta": {
+ "eslint": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-module-utils/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-header": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-header/-/eslint-plugin-header-3.1.1.tgz",
+ "integrity": "sha512-9vlKxuJ4qf793CmeeSrZUvVClw6amtpghq3CuWcB5cUNnWHQhgcqy5eF8oVKFk1G3Y/CbchGfEaw3wiIJaNmVg==",
+ "dev": true,
+ "peerDependencies": {
+ "eslint": ">=7.7.0"
+ }
+ },
+ "node_modules/eslint-plugin-import": {
+ "version": "2.27.5",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz",
+ "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==",
+ "dev": true,
+ "dependencies": {
+ "array-includes": "^3.1.6",
+ "array.prototype.flat": "^1.3.1",
+ "array.prototype.flatmap": "^1.3.1",
+ "debug": "^3.2.7",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.7",
+ "eslint-module-utils": "^2.7.4",
+ "has": "^1.0.3",
+ "is-core-module": "^2.11.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "^3.1.2",
+ "object.values": "^1.1.6",
+ "resolve": "^1.22.1",
+ "semver": "^6.3.0",
+ "tsconfig-paths": "^3.14.1"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-plugin-prettier": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.0.tgz",
+ "integrity": "sha512-AgaZCVuYDXHUGxj/ZGu1u8H8CYgDY3iG6w5kUFw4AzMVXzB7VvbKgYR4nATIN+OvUrghMbiDLeimVjVY5ilq3w==",
+ "dev": true,
+ "dependencies": {
+ "prettier-linter-helpers": "^1.0.0",
+ "synckit": "^0.8.5"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/prettier"
+ },
+ "peerDependencies": {
+ "@types/eslint": ">=8.0.0",
+ "eslint": ">=8.0.0",
+ "prettier": ">=3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/eslint": {
+ "optional": true
+ },
+ "eslint-config-prettier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz",
+ "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/eslint-scope": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz",
+ "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/espree": {
+ "version": "9.6.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.0.tgz",
+ "integrity": "sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "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/esquery": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
+ "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esquery/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "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.6.1",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.1.tgz",
+ "integrity": "sha512-XEdDLonERCU1n9uR56/Stx9OqojaLAQtZf9PrCHH9Hl8YXiEIka3H4NXJ3NOIBmQJTg7+j7buh34PMHfJujc8g==",
+ "dev": true,
+ "dependencies": {
+ "@jest/expect-utils": "^29.6.1",
+ "@types/node": "*",
+ "jest-get-type": "^29.4.3",
+ "jest-matcher-utils": "^29.6.1",
+ "jest-message-util": "^29.6.1",
+ "jest-util": "^29.6.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/exponential-backoff": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz",
+ "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==",
+ "dev": true
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "node_modules/fast-diff": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
+ "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
+ "dev": true
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz",
+ "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "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/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "node_modules/fast-memoize": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/fast-memoize/-/fast-memoize-2.5.2.tgz",
+ "integrity": "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==",
+ "dev": true
+ },
+ "node_modules/fast-xml-parser": {
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz",
+ "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==",
+ "funding": [
+ {
+ "type": "paypal",
+ "url": "https://paypal.me/naturalintelligence"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "dependencies": {
+ "strnum": "^1.0.5"
+ },
+ "bin": {
+ "fxparser": "src/cli/cli.js"
+ }
+ },
+ "node_modules/fastq": {
+ "version": "1.15.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
+ "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "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/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "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/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+ "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+ "dev": true,
+ "dependencies": {
+ "flatted": "^3.1.0",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
+ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
+ "dev": true
+ },
+ "node_modules/for-each": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
+ "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+ "dev": true,
+ "dependencies": {
+ "is-callable": "^1.1.3"
+ }
+ },
+ "node_modules/foreground-child": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
+ "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.0",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/foreground-child/node_modules/signal-exit": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz",
+ "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/form-data-encoder": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz",
+ "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 14.17"
+ }
+ },
+ "node_modules/fp-and-or": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/fp-and-or/-/fp-and-or-0.1.3.tgz",
+ "integrity": "sha512-wJaE62fLaB3jCYvY2ZHjZvmKK2iiLiiehX38rz5QZxtdN8fVPJDeZUiVvJrHStdTc+23LHlyZuSEKgFc0pxi2g==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/fs-minipass": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.2.tgz",
+ "integrity": "sha512-2GAfyfoaCDRrM6jaOS3UsBts8yJ55VioXdWcOL7dK9zdAuKT71+WBA4ifnNYqVjYv+4SsPxjK0JT4yIIn4cA/g==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^5.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "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.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "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/function.prototype.name": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
+ "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.0",
+ "functions-have-names": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gauge": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz",
+ "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==",
+ "dev": true,
+ "dependencies": {
+ "aproba": "^1.0.3 || ^2.0.0",
+ "color-support": "^1.1.3",
+ "console-control-strings": "^1.1.0",
+ "has-unicode": "^2.0.1",
+ "signal-exit": "^3.0.7",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1",
+ "wide-align": "^1.1.5"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "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-intrinsic": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz",
+ "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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-stdin": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz",
+ "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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/get-symbol-description": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
+ "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/global-dirs": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz",
+ "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==",
+ "dev": true,
+ "dependencies": {
+ "ini": "2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/global-dirs/node_modules/ini": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz",
+ "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/globals": {
+ "version": "13.20.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
+ "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globalthis": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
+ "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
+ "dev": true,
+ "dependencies": {
+ "define-properties": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/got": {
+ "version": "12.6.1",
+ "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz",
+ "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==",
+ "dev": true,
+ "dependencies": {
+ "@sindresorhus/is": "^5.2.0",
+ "@szmarczak/http-timer": "^5.0.1",
+ "cacheable-lookup": "^7.0.0",
+ "cacheable-request": "^10.2.8",
+ "decompress-response": "^6.0.0",
+ "form-data-encoder": "^2.1.2",
+ "get-stream": "^6.0.1",
+ "http2-wrapper": "^2.1.10",
+ "lowercase-keys": "^3.0.0",
+ "p-cancelable": "^3.0.0",
+ "responselike": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/got?sponsor=1"
+ }
+ },
+ "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/grapheme-splitter": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
+ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
+ "dev": true
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true
+ },
+ "node_modules/has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/has-bigints": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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/has-property-descriptors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
+ "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
+ "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
+ "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-unicode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+ "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
+ "dev": true
+ },
+ "node_modules/has-yarn": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-3.0.0.tgz",
+ "integrity": "sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/hosted-git-info": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.2.1.tgz",
+ "integrity": "sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^7.5.1"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/hosted-git-info/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/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/http-cache-semantics": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
+ "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==",
+ "dev": true
+ },
+ "node_modules/http-proxy-agent": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
+ "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==",
+ "dev": true,
+ "dependencies": {
+ "@tootallnate/once": "2",
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/http2-wrapper": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.0.tgz",
+ "integrity": "sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ==",
+ "dev": true,
+ "dependencies": {
+ "quick-lru": "^5.1.1",
+ "resolve-alpn": "^1.2.0"
+ },
+ "engines": {
+ "node": ">=10.19.0"
+ }
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "dev": true,
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "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/humanize-ms": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
+ "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.0.0"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
+ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/ignore-walk": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.3.tgz",
+ "integrity": "sha512-C7FfFoTA+bI10qfeydT8aZbvr91vAEU+2W5BZUlzPec47oNb07SsOfwYrtxuvOYdUApPP/Qlh4DtAO51Ekk2QA==",
+ "dev": true,
+ "dependencies": {
+ "minimatch": "^9.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/ignore-walk/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/ignore-walk/node_modules/minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/import-lazy": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz",
+ "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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/ini": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz",
+ "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==",
+ "dev": true,
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/internal-slot": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz",
+ "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.2.0",
+ "has": "^1.0.3",
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/ip": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
+ "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==",
+ "dev": true
+ },
+ "node_modules/is-array-buffer": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
+ "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.0",
+ "is-typed-array": "^1.1.10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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-bigint": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "dev": true,
+ "dependencies": {
+ "has-bigints": "^1.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-boolean-object": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-ci": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz",
+ "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==",
+ "dev": true,
+ "dependencies": {
+ "ci-info": "^3.2.0"
+ },
+ "bin": {
+ "is-ci": "bin.js"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.12.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz",
+ "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==",
+ "dev": true,
+ "dependencies": {
+ "has": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-docker": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
+ "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
+ "dev": true,
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "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-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-inside-container": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
+ "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
+ "dev": true,
+ "dependencies": {
+ "is-docker": "^3.0.0"
+ },
+ "bin": {
+ "is-inside-container": "cli.js"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-installed-globally": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz",
+ "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==",
+ "dev": true,
+ "dependencies": {
+ "global-dirs": "^3.0.0",
+ "is-path-inside": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-lambda": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
+ "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==",
+ "dev": true
+ },
+ "node_modules/is-negative-zero": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
+ "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-npm": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.0.0.tgz",
+ "integrity": "sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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-number-object": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-obj": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
+ "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
+ "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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/is-string": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+ "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.10",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz",
+ "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==",
+ "dev": true,
+ "dependencies": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
+ "dev": true
+ },
+ "node_modules/is-weakref": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+ "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-wsl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "dev": true,
+ "dependencies": {
+ "is-docker": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-wsl/node_modules/is-docker": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+ "dev": true,
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-yarn-global": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.4.1.tgz",
+ "integrity": "sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "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": "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/istanbul-lib-instrument/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/istanbul-lib-report": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
+ "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==",
+ "dev": true,
+ "dependencies": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^3.0.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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.5",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz",
+ "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==",
+ "dev": true,
+ "dependencies": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jackspeak": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.1.tgz",
+ "integrity": "sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw==",
+ "dev": true,
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/jest": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.1.tgz",
+ "integrity": "sha512-Nirw5B4nn69rVUZtemCQhwxOBhm0nsp3hmtF4rzCeWD7BkjAXRIji7xWQfnTNbz9g0aVsBX6aZK3n+23LM6uDw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/core": "^29.6.1",
+ "@jest/types": "^29.6.1",
+ "import-local": "^3.0.2",
+ "jest-cli": "^29.6.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-changed-files": {
+ "version": "29.5.0",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz",
+ "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==",
+ "dev": true,
+ "dependencies": {
+ "execa": "^5.0.0",
+ "p-limit": "^3.1.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-circus": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.1.tgz",
+ "integrity": "sha512-tPbYLEiBU4MYAL2XoZme/bgfUeotpDBd81lgHLCbDZZFaGmECk0b+/xejPFtmiBP87GgP/y4jplcRpbH+fgCzQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^29.6.1",
+ "@jest/expect": "^29.6.1",
+ "@jest/test-result": "^29.6.1",
+ "@jest/types": "^29.6.1",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "co": "^4.6.0",
+ "dedent": "^0.7.0",
+ "is-generator-fn": "^2.0.0",
+ "jest-each": "^29.6.1",
+ "jest-matcher-utils": "^29.6.1",
+ "jest-message-util": "^29.6.1",
+ "jest-runtime": "^29.6.1",
+ "jest-snapshot": "^29.6.1",
+ "jest-util": "^29.6.1",
+ "p-limit": "^3.1.0",
+ "pretty-format": "^29.6.1",
+ "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.6.1",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.1.tgz",
+ "integrity": "sha512-607dSgTA4ODIN6go9w6xY3EYkyPFGicx51a69H7yfvt7lN53xNswEVLovq+E77VsTRi5fWprLH0yl4DJgE8Ing==",
+ "dev": true,
+ "dependencies": {
+ "@jest/core": "^29.6.1",
+ "@jest/test-result": "^29.6.1",
+ "@jest/types": "^29.6.1",
+ "chalk": "^4.0.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "import-local": "^3.0.2",
+ "jest-config": "^29.6.1",
+ "jest-util": "^29.6.1",
+ "jest-validate": "^29.6.1",
+ "prompts": "^2.0.1",
+ "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.6.1",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.1.tgz",
+ "integrity": "sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/test-sequencer": "^29.6.1",
+ "@jest/types": "^29.6.1",
+ "babel-jest": "^29.6.1",
+ "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.6.1",
+ "jest-environment-node": "^29.6.1",
+ "jest-get-type": "^29.4.3",
+ "jest-regex-util": "^29.4.3",
+ "jest-resolve": "^29.6.1",
+ "jest-runner": "^29.6.1",
+ "jest-util": "^29.6.1",
+ "jest-validate": "^29.6.1",
+ "micromatch": "^4.0.4",
+ "parse-json": "^5.2.0",
+ "pretty-format": "^29.6.1",
+ "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.6.1",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.1.tgz",
+ "integrity": "sha512-FsNCvinvl8oVxpNLttNQX7FAq7vR+gMDGj90tiP7siWw1UdakWUGqrylpsYrpvj908IYckm5Y0Q7azNAozU1Kg==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "diff-sequences": "^29.4.3",
+ "jest-get-type": "^29.4.3",
+ "pretty-format": "^29.6.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-docblock": {
+ "version": "29.4.3",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz",
+ "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==",
+ "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.6.1",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.1.tgz",
+ "integrity": "sha512-n5eoj5eiTHpKQCAVcNTT7DRqeUmJ01hsAL0Q1SMiBHcBcvTKDELixQOGMCpqhbIuTcfC4kMfSnpmDqRgRJcLNQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.1",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.4.3",
+ "jest-util": "^29.6.1",
+ "pretty-format": "^29.6.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-environment-node": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.1.tgz",
+ "integrity": "sha512-ZNIfAiE+foBog24W+2caIldl4Irh8Lx1PUhg/GZ0odM1d/h2qORAsejiFc7zb+SEmYPn1yDZzEDSU5PmDkmVLQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^29.6.1",
+ "@jest/fake-timers": "^29.6.1",
+ "@jest/types": "^29.6.1",
+ "@types/node": "*",
+ "jest-mock": "^29.6.1",
+ "jest-util": "^29.6.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-extended": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jest-extended/-/jest-extended-4.0.0.tgz",
+ "integrity": "sha512-GMhMFdrwhYPB0y+cmI/5esz+F/Xc0OIzKbnr8SaiZ74YcWamxf7sVT78YlA15+JIQMTlpHBEgcxheyRBdHFqPA==",
+ "dev": true,
+ "dependencies": {
+ "jest-diff": "^29.0.0",
+ "jest-get-type": "^29.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "jest": ">=27.2.5"
+ },
+ "peerDependenciesMeta": {
+ "jest": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-get-type": {
+ "version": "29.4.3",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz",
+ "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==",
+ "dev": true,
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-haste-map": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.1.tgz",
+ "integrity": "sha512-0m7f9PZXxOCk1gRACiVgX85knUKPKLPg4oRCjLoqIm9brTHXaorMA0JpmtmVkQiT8nmXyIVoZd/nnH1cfC33ig==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.1",
+ "@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.4.3",
+ "jest-util": "^29.6.1",
+ "jest-worker": "^29.6.1",
+ "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-junit": {
+ "version": "16.0.0",
+ "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-16.0.0.tgz",
+ "integrity": "sha512-A94mmw6NfJab4Fg/BlvVOUXzXgF0XIH6EmTgJ5NDPp4xoKq0Kr7sErb+4Xs9nZvu58pJojz5RFGpqnZYJTrRfQ==",
+ "dev": true,
+ "dependencies": {
+ "mkdirp": "^1.0.4",
+ "strip-ansi": "^6.0.1",
+ "uuid": "^8.3.2",
+ "xml": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=10.12.0"
+ }
+ },
+ "node_modules/jest-leak-detector": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.1.tgz",
+ "integrity": "sha512-OrxMNyZirpOEwkF3UHnIkAiZbtkBWiye+hhBweCHkVbCgyEy71Mwbb5zgeTNYWJBi1qgDVfPC1IwO9dVEeTLwQ==",
+ "dev": true,
+ "dependencies": {
+ "jest-get-type": "^29.4.3",
+ "pretty-format": "^29.6.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-matcher-utils": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.1.tgz",
+ "integrity": "sha512-SLaztw9d2mfQQKHmJXKM0HCbl2PPVld/t9Xa6P9sgiExijviSp7TnZZpw2Fpt+OI3nwUO/slJbOfzfUMKKC5QA==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "jest-diff": "^29.6.1",
+ "jest-get-type": "^29.4.3",
+ "pretty-format": "^29.6.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-message-util": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.1.tgz",
+ "integrity": "sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.1",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.6.1",
+ "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.6.1",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.1.tgz",
+ "integrity": "sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.1",
+ "@types/node": "*",
+ "jest-util": "^29.6.1"
+ },
+ "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.4.3",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz",
+ "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==",
+ "dev": true,
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.1.tgz",
+ "integrity": "sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.6.1",
+ "jest-pnp-resolver": "^1.2.2",
+ "jest-util": "^29.6.1",
+ "jest-validate": "^29.6.1",
+ "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.6.1",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.1.tgz",
+ "integrity": "sha512-BbFvxLXtcldaFOhNMXmHRWx1nXQO5LoXiKSGQcA1LxxirYceZT6ch8KTE1bK3X31TNG/JbkI7OkS/ABexVahiw==",
+ "dev": true,
+ "dependencies": {
+ "jest-regex-util": "^29.4.3",
+ "jest-snapshot": "^29.6.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runner": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.1.tgz",
+ "integrity": "sha512-tw0wb2Q9yhjAQ2w8rHRDxteryyIck7gIzQE4Reu3JuOBpGp96xWgF0nY8MDdejzrLCZKDcp8JlZrBN/EtkQvPQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/console": "^29.6.1",
+ "@jest/environment": "^29.6.1",
+ "@jest/test-result": "^29.6.1",
+ "@jest/transform": "^29.6.1",
+ "@jest/types": "^29.6.1",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "graceful-fs": "^4.2.9",
+ "jest-docblock": "^29.4.3",
+ "jest-environment-node": "^29.6.1",
+ "jest-haste-map": "^29.6.1",
+ "jest-leak-detector": "^29.6.1",
+ "jest-message-util": "^29.6.1",
+ "jest-resolve": "^29.6.1",
+ "jest-runtime": "^29.6.1",
+ "jest-util": "^29.6.1",
+ "jest-watcher": "^29.6.1",
+ "jest-worker": "^29.6.1",
+ "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-runner/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/jest-runtime": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.1.tgz",
+ "integrity": "sha512-D6/AYOA+Lhs5e5il8+5pSLemjtJezUr+8zx+Sn8xlmOux3XOqx4d8l/2udBea8CRPqqrzhsKUsN/gBDE/IcaPQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^29.6.1",
+ "@jest/fake-timers": "^29.6.1",
+ "@jest/globals": "^29.6.1",
+ "@jest/source-map": "^29.6.0",
+ "@jest/test-result": "^29.6.1",
+ "@jest/transform": "^29.6.1",
+ "@jest/types": "^29.6.1",
+ "@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.6.1",
+ "jest-message-util": "^29.6.1",
+ "jest-mock": "^29.6.1",
+ "jest-regex-util": "^29.4.3",
+ "jest-resolve": "^29.6.1",
+ "jest-snapshot": "^29.6.1",
+ "jest-util": "^29.6.1",
+ "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.6.1",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.1.tgz",
+ "integrity": "sha512-G4UQE1QQ6OaCgfY+A0uR1W2AY0tGXUPQpoUClhWHq1Xdnx1H6JOrC2nH5lqnOEqaDgbHFgIwZ7bNq24HpB180A==",
+ "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.6.1",
+ "@jest/transform": "^29.6.1",
+ "@jest/types": "^29.6.1",
+ "@types/prettier": "^2.1.5",
+ "babel-preset-current-node-syntax": "^1.0.0",
+ "chalk": "^4.0.0",
+ "expect": "^29.6.1",
+ "graceful-fs": "^4.2.9",
+ "jest-diff": "^29.6.1",
+ "jest-get-type": "^29.4.3",
+ "jest-matcher-utils": "^29.6.1",
+ "jest-message-util": "^29.6.1",
+ "jest-util": "^29.6.1",
+ "natural-compare": "^1.4.0",
+ "pretty-format": "^29.6.1",
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-util": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.1.tgz",
+ "integrity": "sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.1",
+ "@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.6.1",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.1.tgz",
+ "integrity": "sha512-r3Ds69/0KCN4vx4sYAbGL1EVpZ7MSS0vLmd3gV78O+NAx3PDQQukRU5hNHPXlyqCgFY8XUk7EuTMLugh0KzahA==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.1",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.4.3",
+ "leven": "^3.1.0",
+ "pretty-format": "^29.6.1"
+ },
+ "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.6.1",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.1.tgz",
+ "integrity": "sha512-d4wpjWTS7HEZPaaj8m36QiaP856JthRZkrgcIY/7ISoUWPIillrXM23WPboZVLbiwZBt4/qn2Jke84Sla6JhFA==",
+ "dev": true,
+ "dependencies": {
+ "@jest/test-result": "^29.6.1",
+ "@jest/types": "^29.6.1",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "jest-util": "^29.6.1",
+ "string-length": "^4.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-worker": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.1.tgz",
+ "integrity": "sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "jest-util": "^29.6.1",
+ "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/jju": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz",
+ "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==",
+ "dev": true
+ },
+ "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": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "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-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true
+ },
+ "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/json-parse-helpfulerror": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz",
+ "integrity": "sha512-XgP0FGR77+QhUxjXkwOMkC94k3WtqEBfcnjWqhRd82qTat4SWKRE+9kUnynz/shm3I4ea2+qISvTIeGTNU7kJg==",
+ "dev": true,
+ "dependencies": {
+ "jju": "^1.1.0"
+ }
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "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/jsonlines": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsonlines/-/jsonlines-0.1.1.tgz",
+ "integrity": "sha512-ekDrAGso79Cvf+dtm+mL8OBI2bmAOt3gssYs833De/C9NmIpWDWyUO4zPgB5x2/OhY366dkhgfPMYfwZF7yOZA==",
+ "dev": true
+ },
+ "node_modules/jsonparse": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
+ "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==",
+ "dev": true,
+ "engines": [
+ "node >= 0.2.0"
+ ]
+ },
+ "node_modules/keyv": {
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz",
+ "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==",
+ "dev": true,
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "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/latest-version": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz",
+ "integrity": "sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==",
+ "dev": true,
+ "dependencies": {
+ "package-json": "^8.1.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "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": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
+ },
+ "node_modules/lodash.memoize": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
+ "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==",
+ "dev": true
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "node_modules/lowercase-keys": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz",
+ "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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": "3.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/make-dir/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/make-error": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
+ "dev": true
+ },
+ "node_modules/make-fetch-happen": {
+ "version": "11.1.1",
+ "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz",
+ "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==",
+ "dev": true,
+ "dependencies": {
+ "agentkeepalive": "^4.2.1",
+ "cacache": "^17.0.0",
+ "http-cache-semantics": "^4.1.1",
+ "http-proxy-agent": "^5.0.0",
+ "https-proxy-agent": "^5.0.0",
+ "is-lambda": "^1.0.1",
+ "lru-cache": "^7.7.1",
+ "minipass": "^5.0.0",
+ "minipass-fetch": "^3.0.0",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "negotiator": "^0.6.3",
+ "promise-retry": "^2.0.1",
+ "socks-proxy-agent": "^7.0.0",
+ "ssri": "^10.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/make-fetch-happen/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "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/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "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/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/mimic-response": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz",
+ "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==",
+ "dev": true,
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "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/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
+ "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-collect": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
+ "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minipass-collect/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-collect/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/minipass-fetch": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.3.tgz",
+ "integrity": "sha512-n5ITsTkDqYkYJZjcRWzZt9qnZKCT7nKCosJhHoj7S7zD+BP4jVbWs+odsniw5TA3E0sLomhTKOKjF86wf11PuQ==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^5.0.0",
+ "minipass-sized": "^1.0.3",
+ "minizlib": "^2.1.2"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ },
+ "optionalDependencies": {
+ "encoding": "^0.1.13"
+ }
+ },
+ "node_modules/minipass-flush": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
+ "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minipass-flush/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-flush/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/minipass-json-stream": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz",
+ "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==",
+ "dev": true,
+ "dependencies": {
+ "jsonparse": "^1.3.1",
+ "minipass": "^3.0.0"
+ }
+ },
+ "node_modules/minipass-json-stream/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-json-stream/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/minipass-pipeline": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
+ "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-pipeline/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-pipeline/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/minipass-sized": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz",
+ "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-sized/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-sized/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/minizlib": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+ "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^3.0.0",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minizlib/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minizlib/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "dev": true,
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/mnemonist": {
+ "version": "0.38.3",
+ "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.3.tgz",
+ "integrity": "sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==",
+ "dependencies": {
+ "obliterator": "^1.6.1"
+ }
+ },
+ "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/natural-compare-lite": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
+ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
+ "dev": true
+ },
+ "node_modules/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/node-gyp": {
+ "version": "9.4.0",
+ "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.0.tgz",
+ "integrity": "sha512-dMXsYP6gc9rRbejLXmTbVRYjAHw7ppswsKyMxuxJxxOHzluIO1rGp9TOQgjFJ+2MCqcOcQTOPB/8Xwhr+7s4Eg==",
+ "dev": true,
+ "dependencies": {
+ "env-paths": "^2.2.0",
+ "exponential-backoff": "^3.1.1",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.2.6",
+ "make-fetch-happen": "^11.0.3",
+ "nopt": "^6.0.0",
+ "npmlog": "^6.0.0",
+ "rimraf": "^3.0.2",
+ "semver": "^7.3.5",
+ "tar": "^6.1.2",
+ "which": "^2.0.2"
+ },
+ "bin": {
+ "node-gyp": "bin/node-gyp.js"
+ },
+ "engines": {
+ "node": "^12.13 || ^14.13 || >=16"
+ }
+ },
+ "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/nopt": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz",
+ "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==",
+ "dev": true,
+ "dependencies": {
+ "abbrev": "^1.0.0"
+ },
+ "bin": {
+ "nopt": "bin/nopt.js"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/normalize-package-data": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz",
+ "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==",
+ "dev": true,
+ "dependencies": {
+ "hosted-git-info": "^6.0.0",
+ "is-core-module": "^2.8.1",
+ "semver": "^7.3.5",
+ "validate-npm-package-license": "^3.0.4"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/normalize-package-data/node_modules/hosted-git-info": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz",
+ "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^7.5.1"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/normalize-package-data/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/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/normalize-url": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.0.tgz",
+ "integrity": "sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/npm-bundled": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.0.tgz",
+ "integrity": "sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==",
+ "dev": true,
+ "dependencies": {
+ "npm-normalize-package-bin": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/npm-check-updates": {
+ "version": "16.10.15",
+ "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-16.10.15.tgz",
+ "integrity": "sha512-tmbFF7J1mIbjmnN4DzFRVlEeAaIB/FPRz4o95DWsGB7fT3ZECuxyMMDnvySfoijuWxx8E7pODN0IoKYnEJVxcg==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^5.3.0",
+ "cli-table3": "^0.6.3",
+ "commander": "^10.0.0",
+ "fast-memoize": "^2.5.2",
+ "find-up": "5.0.0",
+ "fp-and-or": "^0.1.3",
+ "get-stdin": "^8.0.0",
+ "globby": "^11.0.4",
+ "hosted-git-info": "^5.1.0",
+ "ini": "^4.1.1",
+ "js-yaml": "^4.1.0",
+ "json-parse-helpfulerror": "^1.0.3",
+ "jsonlines": "^0.1.1",
+ "lodash": "^4.17.21",
+ "minimatch": "^9.0.3",
+ "p-map": "^4.0.0",
+ "pacote": "15.2.0",
+ "parse-github-url": "^1.0.2",
+ "progress": "^2.0.3",
+ "prompts-ncu": "^3.0.0",
+ "rc-config-loader": "^4.1.3",
+ "remote-git-tags": "^3.0.0",
+ "rimraf": "^5.0.1",
+ "semver": "^7.5.3",
+ "semver-utils": "^1.1.4",
+ "source-map-support": "^0.5.21",
+ "spawn-please": "^2.0.1",
+ "strip-json-comments": "^5.0.1",
+ "untildify": "^4.0.0",
+ "update-notifier": "^6.0.2"
+ },
+ "bin": {
+ "ncu": "build/src/bin/cli.js",
+ "npm-check-updates": "build/src/bin/cli.js"
+ },
+ "engines": {
+ "node": ">=14.14"
+ }
+ },
+ "node_modules/npm-check-updates/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/npm-check-updates/node_modules/chalk": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
+ "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
+ "dev": true,
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/npm-check-updates/node_modules/glob": {
+ "version": "10.3.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz",
+ "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==",
+ "dev": true,
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^2.0.3",
+ "minimatch": "^9.0.1",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
+ "path-scurry": "^1.10.1"
+ },
+ "bin": {
+ "glob": "dist/cjs/src/bin.js"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/npm-check-updates/node_modules/minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/npm-check-updates/node_modules/rimraf": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.1.tgz",
+ "integrity": "sha512-OfFZdwtd3lZ+XZzYP/6gTACubwFcHdLRqS9UX3UwpU2dnGQYkPFISRwvM3w9IiB2w7bW5qGo/uAwE4SmXXSKvg==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^10.2.5"
+ },
+ "bin": {
+ "rimraf": "dist/cjs/src/bin.js"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/npm-check-updates/node_modules/strip-json-comments": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.1.tgz",
+ "integrity": "sha512-0fk9zBqO67Nq5M/m45qHCJxylV/DhBlIOVExqgOMiCCrzrhU6tCibRXNqE3jwJLftzE9SNuZtYbpzcO+i9FiKw==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/npm-install-checks": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.1.1.tgz",
+ "integrity": "sha512-dH3GmQL4vsPtld59cOn8uY0iOqRmqKvV+DLGwNXV/Q7MDgD2QfOADWd/mFXcIE5LVhYYGjA3baz6W9JneqnuCw==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^7.1.1"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/npm-normalize-package-bin": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz",
+ "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==",
+ "dev": true,
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/npm-package-arg": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz",
+ "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==",
+ "dev": true,
+ "dependencies": {
+ "hosted-git-info": "^6.0.0",
+ "proc-log": "^3.0.0",
+ "semver": "^7.3.5",
+ "validate-npm-package-name": "^5.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/npm-package-arg/node_modules/hosted-git-info": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz",
+ "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^7.5.1"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/npm-package-arg/node_modules/lru-cache": {
+ "version": "7.18.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
+ "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/npm-packlist": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-7.0.4.tgz",
+ "integrity": "sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==",
+ "dev": true,
+ "dependencies": {
+ "ignore-walk": "^6.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/npm-pick-manifest": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-8.0.1.tgz",
+ "integrity": "sha512-mRtvlBjTsJvfCCdmPtiu2bdlx8d/KXtF7yNXNWe7G0Z36qWA9Ny5zXsI2PfBZEv7SXgoxTmNaTzGSbbzDZChoA==",
+ "dev": true,
+ "dependencies": {
+ "npm-install-checks": "^6.0.0",
+ "npm-normalize-package-bin": "^3.0.0",
+ "npm-package-arg": "^10.0.0",
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/npm-registry-fetch": {
+ "version": "14.0.5",
+ "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-14.0.5.tgz",
+ "integrity": "sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA==",
+ "dev": true,
+ "dependencies": {
+ "make-fetch-happen": "^11.0.0",
+ "minipass": "^5.0.0",
+ "minipass-fetch": "^3.0.0",
+ "minipass-json-stream": "^1.0.1",
+ "minizlib": "^2.1.2",
+ "npm-package-arg": "^10.0.0",
+ "proc-log": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.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/npmlog": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz",
+ "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==",
+ "dev": true,
+ "dependencies": {
+ "are-we-there-yet": "^3.0.0",
+ "console-control-strings": "^1.1.0",
+ "gauge": "^4.0.3",
+ "set-blocking": "^2.0.0"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.12.3",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
+ "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.4",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
+ "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "has-symbols": "^1.0.3",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.values": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz",
+ "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/obliterator": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-1.6.1.tgz",
+ "integrity": "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig=="
+ },
+ "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/open": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz",
+ "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==",
+ "dev": true,
+ "dependencies": {
+ "default-browser": "^4.0.0",
+ "define-lazy-prop": "^3.0.0",
+ "is-inside-container": "^1.0.0",
+ "is-wsl": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
+ "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
+ "dev": true,
+ "dependencies": {
+ "@aashutoshrathi/word-wrap": "^1.2.3",
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-cancelable": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz",
+ "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.20"
+ }
+ },
+ "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": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-map": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+ "dev": true,
+ "dependencies": {
+ "aggregate-error": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "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/package-json": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.1.tgz",
+ "integrity": "sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==",
+ "dev": true,
+ "dependencies": {
+ "got": "^12.1.0",
+ "registry-auth-token": "^5.0.1",
+ "registry-url": "^6.0.0",
+ "semver": "^7.3.7"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/pacote": {
+ "version": "15.2.0",
+ "resolved": "https://registry.npmjs.org/pacote/-/pacote-15.2.0.tgz",
+ "integrity": "sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA==",
+ "dev": true,
+ "dependencies": {
+ "@npmcli/git": "^4.0.0",
+ "@npmcli/installed-package-contents": "^2.0.1",
+ "@npmcli/promise-spawn": "^6.0.1",
+ "@npmcli/run-script": "^6.0.0",
+ "cacache": "^17.0.0",
+ "fs-minipass": "^3.0.0",
+ "minipass": "^5.0.0",
+ "npm-package-arg": "^10.0.0",
+ "npm-packlist": "^7.0.0",
+ "npm-pick-manifest": "^8.0.0",
+ "npm-registry-fetch": "^14.0.0",
+ "proc-log": "^3.0.0",
+ "promise-retry": "^2.0.1",
+ "read-package-json": "^6.0.0",
+ "read-package-json-fast": "^3.0.0",
+ "sigstore": "^1.3.0",
+ "ssri": "^10.0.0",
+ "tar": "^6.1.11"
+ },
+ "bin": {
+ "pacote": "lib/bin.js"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-github-url": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz",
+ "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==",
+ "dev": true,
+ "bin": {
+ "parse-github-url": "cli.js"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "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/path-scurry": {
+ "version": "1.10.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
+ "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^9.1.1 || ^10.0.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-scurry/node_modules/lru-cache": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.0.tgz",
+ "integrity": "sha512-svTf/fzsKHffP42sujkO/Rjs37BCIsQVRCeNYIm9WN8rgT7ffoUnRtZCqU+6BqcSBdv8gwJeTz8knJpgACeQMw==",
+ "dev": true,
+ "engines": {
+ "node": "14 || >=16.14"
+ }
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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/pkg-dir/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/pkg-dir/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/pkg-dir/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/pkg-dir/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/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.0.tgz",
+ "integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==",
+ "dev": true,
+ "peer": true,
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-linter-helpers": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+ "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+ "dev": true,
+ "dependencies": {
+ "fast-diff": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/pretty-format": {
+ "version": "29.6.1",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz",
+ "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==",
+ "dev": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.0",
+ "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/proc-log": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz",
+ "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==",
+ "dev": true,
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/progress": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/projen": {
+ "version": "0.71.133",
+ "resolved": "https://registry.npmjs.org/projen/-/projen-0.71.133.tgz",
+ "integrity": "sha512-q0ZUrcPB7VSZamuos9nIn1gzjXL4KiOHLGmKqTOJWcNTv5VIju+yT205fLA9lkcbnGEY5PyfUdRs53YBUmUsag==",
+ "bundleDependencies": [
+ "@iarna/toml",
+ "case",
+ "chalk",
+ "comment-json",
+ "conventional-changelog-config-spec",
+ "fast-json-patch",
+ "glob",
+ "ini",
+ "semver",
+ "shx",
+ "xmlbuilder2",
+ "yaml",
+ "yargs"
+ ],
+ "dev": true,
+ "dependencies": {
+ "@iarna/toml": "^2.2.5",
+ "case": "^1.6.3",
+ "chalk": "^4.1.2",
+ "comment-json": "4.2.2",
+ "conventional-changelog-config-spec": "^2.1.0",
+ "fast-json-patch": "^3.1.1",
+ "glob": "^8",
+ "ini": "^2.0.0",
+ "semver": "^7.5.4",
+ "shx": "^0.3.4",
+ "xmlbuilder2": "^3.1.1",
+ "yaml": "^2.2.2",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "projen": "bin/projen"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/projen/node_modules/@iarna/toml": {
+ "version": "2.2.5",
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/projen/node_modules/@oozcitak/dom": {
+ "version": "1.15.10",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "@oozcitak/infra": "1.0.8",
+ "@oozcitak/url": "1.0.4",
+ "@oozcitak/util": "8.3.8"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/projen/node_modules/@oozcitak/infra": {
+ "version": "1.0.8",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "@oozcitak/util": "8.3.8"
+ },
+ "engines": {
+ "node": ">=6.0"
+ }
+ },
+ "node_modules/projen/node_modules/@oozcitak/url": {
+ "version": "1.0.4",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "@oozcitak/infra": "1.0.8",
+ "@oozcitak/util": "8.3.8"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/projen/node_modules/@oozcitak/util": {
+ "version": "8.3.8",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/projen/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/projen/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/projen/node_modules/array-timsort": {
+ "version": "1.0.3",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/projen/node_modules/balanced-match": {
+ "version": "1.0.2",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/projen/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/projen/node_modules/case": {
+ "version": "1.6.3",
+ "inBundle": true,
+ "license": "(MIT OR GPL-3.0-or-later)",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/projen/node_modules/chalk": {
+ "version": "4.1.2",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/projen/node_modules/cliui": {
+ "version": "8.0.1",
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/projen/node_modules/color-convert": {
+ "version": "2.0.1",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/projen/node_modules/color-name": {
+ "version": "1.1.4",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/projen/node_modules/comment-json": {
+ "version": "4.2.2",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-timsort": "^1.0.3",
+ "core-util-is": "^1.0.3",
+ "esprima": "^4.0.1",
+ "has-own-prop": "^2.0.0",
+ "repeat-string": "^1.6.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/projen/node_modules/concat-map": {
+ "version": "0.0.1",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/projen/node_modules/conventional-changelog-config-spec": {
+ "version": "2.1.0",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/projen/node_modules/core-util-is": {
+ "version": "1.0.3",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/projen/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/projen/node_modules/escalade": {
+ "version": "3.1.1",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/projen/node_modules/esprima": {
+ "version": "4.0.1",
+ "inBundle": true,
+ "license": "BSD-2-Clause",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/projen/node_modules/fast-json-patch": {
+ "version": "3.1.1",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/projen/node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/projen/node_modules/function-bind": {
+ "version": "1.1.1",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/projen/node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "inBundle": true,
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/projen/node_modules/glob": {
+ "version": "8.1.0",
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^5.0.1",
+ "once": "^1.3.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/projen/node_modules/glob/node_modules/minimatch": {
+ "version": "5.1.6",
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/projen/node_modules/has": {
+ "version": "1.0.3",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/projen/node_modules/has-flag": {
+ "version": "4.0.0",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/projen/node_modules/has-own-prop": {
+ "version": "2.0.0",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/projen/node_modules/inflight": {
+ "version": "1.0.6",
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/projen/node_modules/inherits": {
+ "version": "2.0.4",
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/projen/node_modules/ini": {
+ "version": "2.0.0",
+ "inBundle": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/projen/node_modules/interpret": {
+ "version": "1.4.0",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/projen/node_modules/is-core-module": {
+ "version": "2.12.1",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "has": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/projen/node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/projen/node_modules/minimatch": {
+ "version": "3.1.2",
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/projen/node_modules/minimatch/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/projen/node_modules/minimist": {
+ "version": "1.2.8",
+ "inBundle": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/projen/node_modules/once": {
+ "version": "1.4.0",
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/projen/node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/projen/node_modules/path-parse": {
+ "version": "1.0.7",
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/projen/node_modules/rechoir": {
+ "version": "0.6.2",
+ "inBundle": true,
+ "dependencies": {
+ "resolve": "^1.1.6"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/projen/node_modules/repeat-string": {
+ "version": "1.6.1",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/projen/node_modules/require-directory": {
+ "version": "2.1.1",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/projen/node_modules/resolve": {
+ "version": "1.22.2",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-core-module": "^2.11.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/projen/node_modules/semver": {
+ "version": "7.5.4",
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/projen/node_modules/semver/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/projen/node_modules/shelljs": {
+ "version": "0.8.5",
+ "inBundle": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "glob": "^7.0.0",
+ "interpret": "^1.0.0",
+ "rechoir": "^0.6.2"
+ },
+ "bin": {
+ "shjs": "bin/shjs"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/projen/node_modules/shelljs/node_modules/glob": {
+ "version": "7.2.3",
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/projen/node_modules/shx": {
+ "version": "0.3.4",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "minimist": "^1.2.3",
+ "shelljs": "^0.8.5"
+ },
+ "bin": {
+ "shx": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/projen/node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "inBundle": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/projen/node_modules/string-width": {
+ "version": "4.2.3",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/projen/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/projen/node_modules/supports-color": {
+ "version": "7.2.0",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/projen/node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/projen/node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/projen/node_modules/wrappy": {
+ "version": "1.0.2",
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/projen/node_modules/xmlbuilder2": {
+ "version": "3.1.1",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "@oozcitak/dom": "1.15.10",
+ "@oozcitak/infra": "1.0.8",
+ "@oozcitak/util": "8.3.8",
+ "js-yaml": "3.14.1"
+ },
+ "engines": {
+ "node": ">=12.0"
+ }
+ },
+ "node_modules/projen/node_modules/xmlbuilder2/node_modules/argparse": {
+ "version": "1.0.10",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/projen/node_modules/xmlbuilder2/node_modules/js-yaml": {
+ "version": "3.14.1",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/projen/node_modules/y18n": {
+ "version": "5.0.8",
+ "inBundle": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/projen/node_modules/yallist": {
+ "version": "4.0.0",
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/projen/node_modules/yaml": {
+ "version": "2.3.1",
+ "inBundle": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/projen/node_modules/yargs": {
+ "version": "17.7.2",
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/projen/node_modules/yargs/node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "inBundle": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/promise-inflight": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+ "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
+ "dev": true
+ },
+ "node_modules/promise-retry": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
+ "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
+ "dev": true,
+ "dependencies": {
+ "err-code": "^2.0.2",
+ "retry": "^0.12.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "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/prompts-ncu": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/prompts-ncu/-/prompts-ncu-3.0.0.tgz",
+ "integrity": "sha512-qyz9UxZ5MlPKWVhWrCmSZ1ahm2GVYdjLb8og2sg0IPth1KRuhcggHGuijz0e41dkx35p1t1q3GRISGH7QGALFA==",
+ "dev": true,
+ "dependencies": {
+ "kleur": "^4.0.1",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/prompts-ncu/node_modules/kleur": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz",
+ "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/proto-list": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
+ "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==",
+ "dev": true
+ },
+ "node_modules/punycode": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
+ "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pupa": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz",
+ "integrity": "sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==",
+ "dev": true,
+ "dependencies": {
+ "escape-goat": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=12.20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/pure-rand": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz",
+ "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/dubzzz"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fast-check"
+ }
+ ]
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/quick-lru": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
+ "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/rc": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+ "dev": true,
+ "dependencies": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "bin": {
+ "rc": "cli.js"
+ }
+ },
+ "node_modules/rc-config-loader": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/rc-config-loader/-/rc-config-loader-4.1.3.tgz",
+ "integrity": "sha512-kD7FqML7l800i6pS6pvLyIE2ncbk9Du8Q0gp/4hMPhJU6ZxApkoLcGD8ZeqgiAlfwZ6BlETq6qqe+12DUL207w==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.3.4",
+ "js-yaml": "^4.1.0",
+ "json5": "^2.2.2",
+ "require-from-string": "^2.0.2"
+ }
+ },
+ "node_modules/rc/node_modules/ini": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+ "dev": true
+ },
+ "node_modules/rc/node_modules/strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "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/read-package-json": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.4.tgz",
+ "integrity": "sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^10.2.2",
+ "json-parse-even-better-errors": "^3.0.0",
+ "normalize-package-data": "^5.0.0",
+ "npm-normalize-package-bin": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/read-package-json-fast": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz",
+ "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==",
+ "dev": true,
+ "dependencies": {
+ "json-parse-even-better-errors": "^3.0.0",
+ "npm-normalize-package-bin": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/read-package-json-fast/node_modules/json-parse-even-better-errors": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz",
+ "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==",
+ "dev": true,
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/read-package-json/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/read-package-json/node_modules/glob": {
+ "version": "10.3.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz",
+ "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==",
+ "dev": true,
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^2.0.3",
+ "minimatch": "^9.0.1",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
+ "path-scurry": "^1.10.1"
+ },
+ "bin": {
+ "glob": "dist/cjs/src/bin.js"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/read-package-json/node_modules/json-parse-even-better-errors": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz",
+ "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==",
+ "dev": true,
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/read-package-json/node_modules/minimatch": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+ "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/regexp.prototype.flags": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz",
+ "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "functions-have-names": "^1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/registry-auth-token": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz",
+ "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==",
+ "dev": true,
+ "dependencies": {
+ "@pnpm/npm-conf": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/registry-url": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz",
+ "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==",
+ "dev": true,
+ "dependencies": {
+ "rc": "1.2.8"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/remote-git-tags": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/remote-git-tags/-/remote-git-tags-3.0.0.tgz",
+ "integrity": "sha512-C9hAO4eoEsX+OXA4rla66pXZQ+TLQ8T9dttgQj18yuKlPMTVkIkdYXvlMC55IuUsIkV6DpmQYi10JKFLaU+l7w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.2",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz",
+ "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.11.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-alpn": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
+ "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==",
+ "dev": true
+ },
+ "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-cwd/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-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "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/responselike": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz",
+ "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==",
+ "dev": true,
+ "dependencies": {
+ "lowercase-keys": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/run-applescript": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz",
+ "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==",
+ "dev": true,
+ "dependencies": {
+ "execa": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/safe-regex-test": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz",
+ "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.3",
+ "is-regex": "^1.1.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true,
+ "optional": true
+ },
+ "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/semver-diff": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz",
+ "integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/semver-utils": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/semver-utils/-/semver-utils-1.1.4.tgz",
+ "integrity": "sha512-EjnoLE5OGmDAVV/8YDoN5KiajNadjzIp9BAHOhYeQHt7j0UWxjmgsx4YD48wp4Ue1Qogq38F1GNUJNqF1kKKxA==",
+ "dev": true
+ },
+ "node_modules/semver/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/semver/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/set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
+ "dev": true
+ },
+ "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/side-channel": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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/sigstore": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.7.0.tgz",
+ "integrity": "sha512-KP7QULhWdlu3hlp+jw2EvgWKlOGOY9McLj/jrchLjHNlNPK0KWIwF919cbmOp6QiKXLmPijR2qH/5KYWlbtG9Q==",
+ "dev": true,
+ "dependencies": {
+ "@sigstore/protobuf-specs": "^0.1.0",
+ "@sigstore/tuf": "^1.0.1",
+ "make-fetch-happen": "^11.0.1"
+ },
+ "bin": {
+ "sigstore": "bin/sigstore.js"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "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/smart-buffer": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
+ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz",
+ "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==",
+ "dev": true,
+ "dependencies": {
+ "ip": "^2.0.0",
+ "smart-buffer": "^4.2.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks-proxy-agent": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz",
+ "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==",
+ "dev": true,
+ "dependencies": {
+ "agent-base": "^6.0.2",
+ "debug": "^4.3.3",
+ "socks": "^2.6.2"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "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==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/spawn-please": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/spawn-please/-/spawn-please-2.0.1.tgz",
+ "integrity": "sha512-W+cFbZR2q2mMTfjz5ZGvhBAiX+e/zczFCNlbS9mxiSdYswBXwUuBUT+a0urH+xZZa8f/bs0mXHyZsZHR9hKogA==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.3"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/spdx-correct": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
+ "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
+ "dev": true,
+ "dependencies": {
+ "spdx-expression-parse": "^3.0.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-exceptions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+ "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+ "dev": true
+ },
+ "node_modules/spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
+ "dependencies": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-license-ids": {
+ "version": "3.0.13",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz",
+ "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==",
+ "dev": true
+ },
+ "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/ssri": {
+ "version": "10.0.4",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.4.tgz",
+ "integrity": "sha512-12+IR2CB2C28MMAw0Ncqwj5QbTcs0nGIhgJzYWzDkb21vWmfNI83KS4f3Ci6GI98WreIfG7o9UXp3C0qbpA8nQ==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^5.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "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/stack-utils/node_modules/escape-string-regexp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "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/string-width-cjs": {
+ "name": "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/string.prototype.trim": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz",
+ "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz",
+ "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz",
+ "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.20.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "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-ansi-cjs": {
+ "name": "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/strnum": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
+ "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA=="
+ },
+ "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/synckit": {
+ "version": "0.8.5",
+ "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz",
+ "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==",
+ "dev": true,
+ "dependencies": {
+ "@pkgr/utils": "^2.3.1",
+ "tslib": "^2.5.0"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
+ "node_modules/tar": {
+ "version": "6.1.15",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz",
+ "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==",
+ "dev": true,
+ "dependencies": {
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.0.0",
+ "minipass": "^5.0.0",
+ "minizlib": "^2.1.1",
+ "mkdirp": "^1.0.3",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/tar/node_modules/fs-minipass": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+ "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+ "dev": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tar/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/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/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "node_modules/titleize": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz",
+ "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/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/ts-api-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz",
+ "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=16.13.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.2.0"
+ }
+ },
+ "node_modules/ts-jest": {
+ "version": "29.1.1",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz",
+ "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==",
+ "dev": true,
+ "dependencies": {
+ "bs-logger": "0.x",
+ "fast-json-stable-stringify": "2.x",
+ "jest-util": "^29.0.0",
+ "json5": "^2.2.3",
+ "lodash.memoize": "4.x",
+ "make-error": "1.x",
+ "semver": "^7.5.3",
+ "yargs-parser": "^21.0.1"
+ },
+ "bin": {
+ "ts-jest": "cli.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": ">=7.0.0-beta.0 <8",
+ "@jest/types": "^29.0.0",
+ "babel-jest": "^29.0.0",
+ "jest": "^29.0.0",
+ "typescript": ">=4.3 <6"
+ },
+ "peerDependenciesMeta": {
+ "@babel/core": {
+ "optional": true
+ },
+ "@jest/types": {
+ "optional": true
+ },
+ "babel-jest": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ts-node": {
+ "version": "10.9.1",
+ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
+ "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==",
+ "dev": true,
+ "dependencies": {
+ "@cspotcode/source-map-support": "^0.8.0",
+ "@tsconfig/node10": "^1.0.7",
+ "@tsconfig/node12": "^1.0.7",
+ "@tsconfig/node14": "^1.0.0",
+ "@tsconfig/node16": "^1.0.2",
+ "acorn": "^8.4.1",
+ "acorn-walk": "^8.1.1",
+ "arg": "^4.1.0",
+ "create-require": "^1.1.0",
+ "diff": "^4.0.1",
+ "make-error": "^1.1.1",
+ "v8-compile-cache-lib": "^3.0.1",
+ "yn": "3.1.1"
+ },
+ "bin": {
+ "ts-node": "dist/bin.js",
+ "ts-node-cwd": "dist/bin-cwd.js",
+ "ts-node-esm": "dist/bin-esm.js",
+ "ts-node-script": "dist/bin-script.js",
+ "ts-node-transpile-only": "dist/bin-transpile.js",
+ "ts-script": "dist/bin-script-deprecated.js"
+ },
+ "peerDependencies": {
+ "@swc/core": ">=1.2.50",
+ "@swc/wasm": ">=1.2.50",
+ "@types/node": "*",
+ "typescript": ">=2.7"
+ },
+ "peerDependenciesMeta": {
+ "@swc/core": {
+ "optional": true
+ },
+ "@swc/wasm": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/tsconfig-paths": {
+ "version": "3.14.2",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz",
+ "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==",
+ "dev": true,
+ "dependencies": {
+ "@types/json5": "^0.0.29",
+ "json5": "^1.0.2",
+ "minimist": "^1.2.6",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "node_modules/tsconfig-paths/node_modules/json5": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+ "dev": true,
+ "dependencies": {
+ "minimist": "^1.2.0"
+ },
+ "bin": {
+ "json5": "lib/cli.js"
+ }
+ },
+ "node_modules/tsconfig-paths/node_modules/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz",
+ "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA=="
+ },
+ "node_modules/tuf-js": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.7.tgz",
+ "integrity": "sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==",
+ "dev": true,
+ "dependencies": {
+ "@tufjs/models": "1.0.4",
+ "debug": "^4.3.4",
+ "make-fetch-happen": "^11.1.1"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.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.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typed-array-length": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
+ "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "is-typed-array": "^1.1.9"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typedarray-to-buffer": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
+ "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
+ "dev": true,
+ "dependencies": {
+ "is-typedarray": "^1.0.0"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz",
+ "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/unbox-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
+ "which-boxed-primitive": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/unique-filename": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz",
+ "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==",
+ "dev": true,
+ "dependencies": {
+ "unique-slug": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/unique-slug": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz",
+ "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==",
+ "dev": true,
+ "dependencies": {
+ "imurmurhash": "^0.1.4"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "node_modules/unique-string": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz",
+ "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==",
+ "dev": true,
+ "dependencies": {
+ "crypto-random-string": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/untildify": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz",
+ "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/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/update-notifier": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-6.0.2.tgz",
+ "integrity": "sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==",
+ "dev": true,
+ "dependencies": {
+ "boxen": "^7.0.0",
+ "chalk": "^5.0.1",
+ "configstore": "^6.0.0",
+ "has-yarn": "^3.0.0",
+ "import-lazy": "^4.0.0",
+ "is-ci": "^3.0.1",
+ "is-installed-globally": "^0.4.0",
+ "is-npm": "^6.0.0",
+ "is-yarn-global": "^0.4.0",
+ "latest-version": "^7.0.0",
+ "pupa": "^3.1.0",
+ "semver": "^7.3.7",
+ "semver-diff": "^4.0.0",
+ "xdg-basedir": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/yeoman/update-notifier?sponsor=1"
+ }
+ },
+ "node_modules/update-notifier/node_modules/chalk": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
+ "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
+ "dev": true,
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "dev": true
+ },
+ "node_modules/uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/v8-compile-cache-lib": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
+ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
+ "dev": true
+ },
+ "node_modules/v8-to-istanbul": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz",
+ "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==",
+ "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/@jridgewell/resolve-uri": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/v8-to-istanbul/node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.14",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+ "dev": true
+ },
+ "node_modules/v8-to-istanbul/node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.18",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz",
+ "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "3.1.0",
+ "@jridgewell/sourcemap-codec": "1.4.14"
+ }
+ },
+ "node_modules/v8-to-istanbul/node_modules/convert-source-map": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
+ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
+ "dev": true
+ },
+ "node_modules/validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
+ "dev": true,
+ "dependencies": {
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
+ }
+ },
+ "node_modules/validate-npm-package-name": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz",
+ "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==",
+ "dev": true,
+ "dependencies": {
+ "builtins": "^5.0.0"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
+ },
+ "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/which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dev": true,
+ "dependencies": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.10",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.10.tgz",
+ "integrity": "sha512-uxoA5vLUfRPdjCuJ1h5LlYdmTLbYfums398v3WLkM+i/Wltl2/XyZpQWKbN++ck5L64SR/grOHqtXCUKmlZPNA==",
+ "dev": true,
+ "dependencies": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-tostringtag": "^1.0.0",
+ "is-typed-array": "^1.1.10"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/wide-align": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
+ "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^1.0.2 || 2 || 3 || 4"
+ }
+ },
+ "node_modules/widest-line": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz",
+ "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/widest-line/node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/widest-line/node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true
+ },
+ "node_modules/widest-line/node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dev": true,
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/widest-line/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "name": "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/wrap-ansi/node_modules/ansi-regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+ "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true
+ },
+ "node_modules/wrap-ansi/node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dev": true,
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-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/xdg-basedir": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz",
+ "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/xml": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz",
+ "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==",
+ "dev": true
+ },
+ "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/yn": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+ "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 00000000..f2c47ae0
--- /dev/null
+++ b/package.json
@@ -0,0 +1,81 @@
+{
+ "name": "instance-scheduler-on-aws",
+ "description": "Instance Scheduler on AWS (SO0030)",
+ "scripts": {
+ "build": "npx projen build",
+ "bundle": "npx projen bundle",
+ "clobber": "npx projen clobber",
+ "compile": "npx projen compile",
+ "default": "npx projen default",
+ "deploy": "npx projen deploy",
+ "destroy": "npx projen destroy",
+ "diff": "npx projen diff",
+ "e2e-tests": "npx projen e2e-tests",
+ "eject": "npx projen eject",
+ "package": "npx projen package",
+ "post-compile": "npx projen post-compile",
+ "post-upgrade": "npx projen post-upgrade",
+ "pre-compile": "npx projen pre-compile",
+ "synth": "npx projen synth",
+ "synth:silent": "npx projen synth:silent",
+ "test": "npx projen test",
+ "test:app": "npx projen test:app",
+ "test:app:ci": "npx projen test:app:ci",
+ "test:cdk": "npx projen test:cdk",
+ "test:cdk:ci": "npx projen test:cdk:ci",
+ "test:ci": "npx projen test:ci",
+ "test:cli": "npx projen test:cli",
+ "test:cli:ci": "npx projen test:cli:ci",
+ "test:eslint": "npx projen test:eslint",
+ "test:prettier": "npx projen test:prettier",
+ "test:update": "npx projen test:update",
+ "test:watch": "npx projen test:watch",
+ "upgrade": "npx projen upgrade",
+ "watch": "npx projen watch",
+ "projen": "npx projen"
+ },
+ "author": {
+ "name": "Amazon Web Services",
+ "url": "https://aws.amazon.com/solutions",
+ "organization": true
+ },
+ "devDependencies": {
+ "@types/jest": "^29.5.3",
+ "@types/node": "^18",
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
+ "aws-cdk": "^2.87.0",
+ "esbuild": "^0.18.11",
+ "eslint": "^8.44.0",
+ "eslint-config-prettier": "^8.8.0",
+ "eslint-plugin-header": "^3.1.1",
+ "eslint-plugin-import": "^2.27.5",
+ "eslint-plugin-prettier": "^5.0.0",
+ "jest": "^29.6.1",
+ "jest-extended": "^4.0.0",
+ "jest-junit": "^16.0.0",
+ "npm-check-updates": "^16",
+ "projen": "^0.71.133",
+ "ts-jest": "^29.1.1",
+ "ts-node": "^10.9.1",
+ "typescript": "^5.1.6"
+ },
+ "dependencies": {
+ "@aws-cdk/aws-lambda-python-alpha": "^2.87.0-alpha.0",
+ "@aws-cdk/aws-servicecatalogappregistry-alpha": "^2.87.0-alpha.0",
+ "@aws-sdk/client-dynamodb": "^3.369.0",
+ "@aws-sdk/client-ec2": "^3.369.0",
+ "@aws-sdk/client-rds": "^3.369.0",
+ "@aws-sdk/client-ssm": "^3.369.0",
+ "@aws-solutions-constructs/aws-lambda-dynamodb": "^2.41.0",
+ "aws-cdk-lib": "^2.87.0",
+ "cdk-nag": "^2.27.67",
+ "constructs": "^10.0.5",
+ "source-map-support": "^0.5.21"
+ },
+ "engines": {
+ "node": ">= 18.0.0"
+ },
+ "license": "Apache-2.0",
+ "version": "1.5.1",
+ "//": "~~ Generated by projen. To modify, edit .projenrc.ts and run \"npx projen\"."
+}
diff --git a/projenrc/PULL_REQUEST_TEMPLATE.md b/projenrc/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 00000000..74a7a79a
--- /dev/null
+++ b/projenrc/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,6 @@
+_Issue #, if available:_
+
+_Description of changes:_
+
+By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the
+terms of your choice.
diff --git a/sonar-project.properties b/sonar-project.properties
index 13a956b9..93a77f38 100644
--- a/sonar-project.properties
+++ b/sonar-project.properties
@@ -1,68 +1,31 @@
-# Note: Currently testing and supported with code coverage sonarqube
-# collection for python lambda (python pytest, python unittest) and javascript jest
-# and CDK TypeScript
+# .git/ not available from codecommit
+sonar.scm.disabled = true
-# Uncomment to enable debugging by default
-#sonar.verbose=true
-#sonar.log.level=DEBUG
+sonar.sources = \
+ source/, \
+ build/cdk.out/
-# Disable if needed
-#sonar.scm.disabled=true
-
-#
-# Refer to https://docs.sonarqube.org/latest/project-administration/narrowing-the-focus/
-# for details on sources and exclusions. Note also .gitignore
-#
-sonar.sources= \
- source
-
-sonar.exclusions= \
- **/test/**, \
- **/tests/**, \
- **/e2e-tests/**, \
+sonar.exclusions = \
+ **/tests/**/*, \
+ **/e2e-tests/**/*, \
**/jest.config.ts, \
- bin/**, \
- source/app/certifi/**/*, \
- source/app/charset_normalizer/**/*, \
- source/app/idna/**/*, \
- source/app/pytz/**/*, \
- source/app/urllib3/**/*, \
- source/app/requests/**/*, \
- source/app/chardet/**/*, \
- source/app/build/lib/**/*, \
- source/app/version.py, \
- source/app/update-build-number.py, \
- deployment/**, \
- coverage/**
-
-
+ **/asset.*/**/*
sonar.tests= \
source/app/tests, \
source/cli/tests, \
- source/infrastructure/instance-scheduler/tests, \
- source/infrastructure/pipeline/e2e-tests
+ source/instance-scheduler/tests, \
+ source/pipeline/e2e-tests
-# Code coverage Specific Properties
-# sonar.coverage.exclusions=\
-# source/bin/**
+sonar.python.version = 3.8, 3.9, 3.10, 3.11
-sonar.sourceEncoding=UTF-8
+sonar.python.coverage.reportPaths = \
+ deployment/coverage-reports/cli-coverage.xml, \
+ deployment/coverage-reports/lambda-coverage.xml
-## Python Specific Properties*
-# coverage
-# https://docs.sonarqube.org/pages/viewpage.action?pageId=4784149
-# Comma-separated list of ant pattern describing paths to coverage reports, relative to projects
-# root. Leave unset to use the default ("coverage-reports/*coverage-*.xml").
-sonar.python.coverage.reportPaths= \
- deployment/coverage-reports/cli-coverage.xml, \
- deployment/coverage-reports/lambda-coverage.xml
-
-sonar.python.version=3.9, 3.10, 3.11
-
-# Sensor SonarJS Coverage [javascript] was not allowing globbing
-# for sonar.javascript.lcov.reportPaths such as this
-# source/test/coverage-reports/jest/*/lcov.info
-# so we have to provide an explicit list of reportPaths
-sonar.javascript.lcov.reportPaths= \
+sonar.javascript.lcov.reportPaths = \
deployment/coverage-reports/cdk-coverage/lcov.info
+
+sonar.issue.ignore.multicriteria = ts1
+sonar.issue.ignore.multicriteria.ts1.ruleKey = typescript:S1848
+sonar.issue.ignore.multicriteria.ts1.resourceKey = **/*.ts
diff --git a/source/app/.coveragerc b/source/app/.coveragerc
new file mode 100644
index 00000000..90626ce5
--- /dev/null
+++ b/source/app/.coveragerc
@@ -0,0 +1,7 @@
+[run]
+branch = true
+source = instance_scheduler
+
+[report]
+exclude_lines =
+ if TYPE_CHECKING:
diff --git a/source/app/instance_scheduler/__init__.py b/source/app/instance_scheduler/__init__.py
index 04f8b7b7..07045752 100644
--- a/source/app/instance_scheduler/__init__.py
+++ b/source/app/instance_scheduler/__init__.py
@@ -1,2 +1,19 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
+from typing import Literal
+
+UnknownState = Literal["unknown"]
+AnyState = Literal["any"]
+StoppedState = Literal["stopped"]
+StoppedForResizeState = Literal["stopped_for_resize"]
+RunningState = Literal["running"]
+RetainRunningState = Literal["retain-running"]
+
+ScheduleState = (
+ UnknownState
+ | AnyState
+ | StoppedState
+ | StoppedForResizeState
+ | RunningState
+ | RetainRunningState
+)
diff --git a/source/app/instance_scheduler/boto_retry/__init__.py b/source/app/instance_scheduler/boto_retry/__init__.py
index 6d22e55b..9535fdb4 100644
--- a/source/app/instance_scheduler/boto_retry/__init__.py
+++ b/source/app/instance_scheduler/boto_retry/__init__.py
@@ -1,39 +1,19 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
+from typing import Any, Optional
+from boto3 import Session
-import os
+from instance_scheduler.util import get_boto_config
-import boto3
-import botocore.config
+def get_client_with_standard_retry(
+ service_name: str, region: Optional[str] = None, session: Optional[Session] = None
+) -> Any:
+ aws_session = session if session is not None else Session()
-def get_client_with_standard_retry(service_name, region=None, session=None):
- """
- Creates a bot3 client for the specified service name and region. The return client will have additional method for the
- specified methods that are wrapped with the logic of the specified wait strategy or the default strategy for that service.
- The method names must be valid for the boto3 service client. The name of the added functions is the name of the original
- function plus the (default) value of method_suffix parameter
- :param service_name: Name of the service
- :param region: Region for the client
- :param session: Boto3 session, if None a new session will be created
- :return: Client for the service with additional method that use retry logic
- """
- args = {
- "service_name": service_name,
- "region_name": region,
- "config": standard_retries_client_config(),
- }
-
- aws_session = session if session is not None else boto3.Session()
-
- result = aws_session.client(**args)
+ result = aws_session.client(
+ service_name=service_name, region_name=region, config=get_boto_config()
+ )
return result
-
-
-def standard_retries_client_config():
- return botocore.config.Config(
- user_agent_extra=os.getenv("USER_AGENT_EXTRA", None),
- retries={"max_attempts": 5, "mode": "standard"},
- )
diff --git a/source/app/instance_scheduler/configuration/__init__.py b/source/app/instance_scheduler/configuration/__init__.py
index f579305f..7ad091bd 100644
--- a/source/app/instance_scheduler/configuration/__init__.py
+++ b/source/app/instance_scheduler/configuration/__init__.py
@@ -1,26 +1,18 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-import os
+from typing import Optional
from instance_scheduler.configuration.config_dynamodb_adapter import (
ConfigDynamodbAdapter,
)
+from instance_scheduler.configuration.scheduler_config import GlobalConfig
from instance_scheduler.configuration.scheduler_config_builder import (
SchedulerConfigBuilder,
)
+from instance_scheduler.util.app_env import get_app_env
+from instance_scheduler.util.logger import Logger
-# environment parameter for configuration table
-ENV_CONFIG = "CONFIG_TABLE"
-ENV_STATE = "STATE_TABLE"
-ENV_ACCOUNT = "ACCOUNT"
ENV_STACK = "STACK_NAME"
-ENV_TAG_NAME = "TAG_NAME"
-ENV_SCHEDULE_FREQUENCY = "SCHEDULER_FREQUENCY"
-ENV_TRACE = "TRACE"
-ENV_ENABLE_SSM_MAINTENANCE_WINDOWS = "ENABLE_SSM_MAINTENANCE_WINDOWS"
-ENV_USER_AGENT = "USER_AGENT"
-ENV_SCHEDULER_RULE = "SCHEDULER_RULE"
# name of months
MONTH_NAMES = [
@@ -56,7 +48,7 @@
TRACE = "trace"
# enable SSM maintenance windows
-ENABLE_SSM_MAINTENANCE_WINDOWS = "enable_SSM_maintenance_windows"
+ENABLE_SSM_MAINTENANCE_WINDOWS = "enable_ssm_maintenance_windows"
# metrics flag
METRICS = "use_metrics"
@@ -149,24 +141,24 @@
TAG_VAL_DAY = "day"
TAG_VAL_TIMEZONE = "timezone"
-__configuration = None
+__configuration: Optional[GlobalConfig] = None
-def get_scheduler_configuration(logger):
+def get_global_configuration(logger: Optional[Logger]) -> GlobalConfig:
"""
Returns the scheduler configuration
:return: scheduler configuration
"""
global __configuration
if __configuration is None:
- configdata = ConfigDynamodbAdapter(os.getenv(ENV_CONFIG)).config
+ configdata = ConfigDynamodbAdapter(get_app_env().config_table_name).config
__configuration = SchedulerConfigBuilder(logger=logger).build(configdata)
if logger is not None:
logger.debug("Configuration loaded\n{}", str(__configuration))
return __configuration
-def unload_scheduler_configuration():
+def unload_global_configuration() -> None:
"""
Force the configuration to unload
:return:
diff --git a/source/app/instance_scheduler/configuration/config_admin.py b/source/app/instance_scheduler/configuration/config_admin.py
index e1630d3d..25a02269 100644
--- a/source/app/instance_scheduler/configuration/config_admin.py
+++ b/source/app/instance_scheduler/configuration/config_admin.py
@@ -1,22 +1,19 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-
import json
-import os
import re
-import pytz
from datetime import datetime, timedelta
+from typing import TYPE_CHECKING, Any, Literal, Optional, TypedDict, TypeVar
+from zoneinfo import ZoneInfo
-import boto3
from boto3.dynamodb.conditions import Key
-from instance_scheduler import configuration
-from instance_scheduler.util.dynamodb_utils import DynamoDBUtils
+from instance_scheduler import ScheduleState, configuration
from instance_scheduler.configuration.config_dynamodb_adapter import (
ConfigDynamodbAdapter,
)
-from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler.configuration.instance_schedule import Instance
+from instance_scheduler.configuration.scheduler_config import GlobalConfig
from instance_scheduler.configuration.scheduler_config_builder import (
SchedulerConfigBuilder,
)
@@ -29,7 +26,17 @@
from instance_scheduler.configuration.setbuilders.weekday_setbuilder import (
WeekdaySetBuilder,
)
-from instance_scheduler.util.named_tuple_builder import as_namedtuple
+from instance_scheduler.util.app_env import get_app_env
+from instance_scheduler.util.dynamodb_utils import DynamoDBUtils
+from instance_scheduler.util.logger import Logger
+
+if TYPE_CHECKING:
+ from aws_lambda_powertools.utilities.typing import LambdaContext
+
+ T = TypeVar("T")
+else:
+ LambdaContext = object
+ T = object
ERR_PERIOD_BEGIN_LATER_THAN_END = (
"error: period begintime {} can not be later than endtime {}"
@@ -40,17 +47,14 @@
)
ERR_CREATE_PERIOD_EXISTS = "error: period {} already exists"
ERR_CREATE_SCHEDULE_EXISTS = "error: schedule {} already exists"
-ERR_DEL_PERIOD_EMPTY = "error: period name parameter can not be empty"
ERR_DEL_PERIOD_IN_USE = (
"error: period {} can not be deleted because it is still used in schedule(s) {}"
)
-ERR_DEL_PERIOD_NOT_FOUND = "not found: period {} does not exist"
+ERR_PERIOD_NOT_FOUND = "not found: period {} does not exist"
ERR_DEL_SCHEDULE_NAME_EMPTY = "error: schedule name parameter can not be empty"
-ERR_DEL_SCHEDULE_NOT_FOUND = "not found: schedule {} does not exist"
-ERR_GET_EMPTY_PERIOD_NAME = "error: period name parameter can not be empty"
-ERR_GET_PERIOD_NOT_FOUND = "not found: period {} does not exist"
+ERR_SCHEDULE_NOT_FOUND = "not found: schedule {} does not exist"
+ERR_EMPTY_PERIOD_NAME = "error: period name parameter can not be empty"
ERR_GET_SCHEDULE_NAME_EMPTY = "error: error schedule name parameter can not be empty"
-ERR_GET_SCHEDULE_NOT_FOUND = "not found: schedule {} does not exist"
ERR_GET_USAGE_INVALID_END_DATE = (
"error: invalid enddate {}, must be a valid date in format yyyymmdd {}"
)
@@ -60,7 +64,6 @@
ERR_GET_USAGE_SCHEDULE_NAME_EMPTY = (
"error: error schedule name parameter can not be empty"
)
-ERR_GET_USAGE_SCHEDULE_NOT_FOUND = "not found: schedule {} does not exist"
ERR_GET_USAGE_START_MUST_BE_LESS_OR_EQUAL_STOP = (
"stop_date must be equal or later than start_date"
)
@@ -85,10 +88,7 @@
"error: {} for parameter {} is not a valid boolean value"
)
ERR_UPDATE_INVALID_TZ_PARAMETER = "error: {} is not a valid time zone for parameter {}"
-ERR_UPDATE_PERIOD_NAME_EMPTY = "error: period name parameter can not be empty"
-ERR_UPDATE_PERIOD_NOT_FOUND = "not found: period {} does not exist"
ERR_UPDATE_SCHEDULE_NAME_EMPTY = "error: schedule name parameter can not be empty"
-ERR_UPDATE_SCHEDULE_NOT_FOUND = "not found: schedule {} does not exist"
ERR_UPDATE_TAGNAME_EMPTY = "error: tagname parameter must be specified"
ERR_UPDATE_UNKNOWN_PARAMETER = "error: {} is not a valid parameter"
ERR_UPDATE_UNKNOWN_SERVICE = "{} is not a supported service"
@@ -103,6 +103,70 @@
"Remove permission for account {} to put events on event bus, sid = {}"
)
+ConfigTableConfigItemType = Literal["config"]
+ConfigTableScheduleItemType = Literal["schedule"]
+ConfigTablePeriodItemType = Literal["period"]
+
+ConfigTableItemType = (
+ ConfigTableConfigItemType | ConfigTableScheduleItemType | ConfigTablePeriodItemType
+)
+
+
+class ConfigTableItem(TypedDict, total=False):
+ type: ConfigTableItemType
+ name: str
+
+
+class ConfigTableConfigItem(ConfigTableItem):
+ use_metrics: bool
+ remote_account_ids: set[str]
+ organization_id: str
+ scheduler_role_name: str
+ namespace: str
+ aws_partition: str
+ default_timezone: str
+ regions: set[str] | list[str]
+ schedule_lambda_account: bool
+ tagname: str
+ trace: bool
+ enable_ssm_maintenance_windows: bool
+ scheduled_services: set[str]
+ schedule_clusters: bool
+ create_rds_snapshot: bool
+ started_tags: str
+ stopped_tags: str
+
+
+OverrideStatusRunning = Literal["running"]
+OverrideStatusStopped = Literal["stopped"]
+
+OverrideStatus = OverrideStatusRunning | OverrideStatusStopped
+
+
+class ConfigTableScheduleItem(ConfigTableItem, total=False):
+ timezone: str
+ periods: set[str]
+ description: str
+ overwrite: bool
+ use_metrics: bool
+ stop_new_instances: bool
+ use_maintenance_window: bool
+ ssm_maintenance_window: str
+ retain_running: bool
+ enforced: bool
+ hibernate: bool
+ override_status: OverrideStatus
+ configured_in_stack: str
+
+
+class ConfigTablePeriodItem(ConfigTableItem, total=False):
+ begintime: str
+ endtime: str
+ weekdays: set[str]
+ monthdays: set[str]
+ months: set[str]
+ description: str
+
class ConfigAdmin:
"""
@@ -120,7 +184,7 @@ class CustomEncoder(json.JSONEncoder):
Custom encoding to handle unsupported data types
"""
- def default(self, o):
+ def default(self, o: Any) -> Any:
if isinstance(o, set):
return list(o)
if isinstance(o, datetime):
@@ -128,20 +192,24 @@ def default(self, o):
return json.JSONEncoder.default(self, o)
- def __init__(self, logger, context):
+ def __init__(
+ self, logger: Optional[Logger], context: Optional[LambdaContext]
+ ) -> None:
"""
Initializes the config API
:param logger: logger for the admin api
:param context: Lambda context
"""
self._table_name = self.table_name
- self._table = DynamoDBUtils.get_dynamodb_table_resource_ref(self._table_name)
- self._configuration = None
+ self._table: Any = DynamoDBUtils.get_dynamodb_table_resource_ref(
+ self._table_name
+ )
+ self._configuration: Optional[GlobalConfig] = None
self._logger = logger
self._context = context
@property
- def configuration(self):
+ def configuration(self) -> GlobalConfig:
"""
Returns and cached configuration
:return: scheduler configuration
@@ -154,25 +222,10 @@ def configuration(self):
return self._configuration
@property
- def table_name(self):
- """
- Returns the name of the config table
- :return: name of the config
- """
- return os.getenv(configuration.ENV_CONFIG)
+ def table_name(self) -> str:
+ return get_app_env().config_table_name
- def get_config_as_json(self):
- """
- Gets the configuration as json
- :return:
- """
- resp = self._table.get_item_with_rerties(
- Key={"name": "scheduler", "type": "config"}, ConsistentRead=True
- )
- item = resp.get("Item", {})
- return self._for_output(item)
-
- def update_config(self, **settings):
+ def update_config(self, settings: ConfigTableConfigItem) -> Any:
"""
Updates configuration, validates new values
:param settings: settings values
@@ -199,7 +252,7 @@ def update_config(self, **settings):
configuration.STOPPED_TAGS,
]
- checked_settings = {}
+ checked_settings: dict[str, str | bool | set[str]] = {}
for attr in settings:
if attr in [ConfigAdmin.TYPE_ATTR, configuration.NAME]:
@@ -210,11 +263,11 @@ def update_config(self, **settings):
raise ValueError(ERR_UPDATE_UNKNOWN_PARAMETER.format(attr))
# remove None fields
- if settings[attr] is None:
+ if settings[attr] is None: # type: ignore[literal-required]
continue
# remove empty strings
- if len(str(settings[attr])) == 0:
+ if len(str(settings[attr])) == 0: # type: ignore[literal-required]
continue
# make sure these fields are set as sets
@@ -223,8 +276,8 @@ def update_config(self, **settings):
configuration.REMOTE_ACCOUNT_IDS,
configuration.SCHEDULED_SERVICES,
]:
- temp = self._ensure_set(settings[attr])
- if len(settings[attr]) > 0:
+ temp = self._ensure_set(settings[attr]) # type: ignore[literal-required]
+ if len(settings[attr]) > 0: # type: ignore[literal-required]
checked_settings[attr] = temp
continue
@@ -238,17 +291,17 @@ def update_config(self, **settings):
configuration.CREATE_RDS_SNAPSHOT,
configuration.SCHEDULE_CLUSTERS,
]:
- bool_value = self._ensure_bool(settings[attr])
+ bool_value = self._ensure_bool(settings[attr]) # type: ignore[literal-required]
if bool_value is None:
raise ValueError(
- ERR_UPDATE_INVALID_BOOL_PARAM.format(settings[attr], attr)
+ ERR_UPDATE_INVALID_BOOL_PARAM.format(settings[attr], attr) # type: ignore[literal-required]
)
checked_settings[attr] = bool_value
continue
# validate timezone
if attr == configuration.DEFAULT_TIMEZONE:
- default_tz = settings[configuration.DEFAULT_TIMEZONE]
+ default_tz = settings[configuration.DEFAULT_TIMEZONE] # type: ignore[literal-required]
if not SchedulerConfigBuilder.is_valid_timezone(default_tz):
raise ValueError(
ERR_UPDATE_INVALID_TZ_PARAMETER.format(
@@ -258,12 +311,12 @@ def update_config(self, **settings):
checked_settings[attr] = default_tz
continue
- checked_settings[attr] = settings[attr]
+ checked_settings[attr] = settings[attr] # type: ignore[literal-required]
if configuration.TAGNAME not in settings:
raise ValueError(ERR_UPDATE_TAGNAME_EMPTY)
- for service in settings.get(configuration.SCHEDULED_SERVICES, []):
+ for service in settings.get("scheduled_services", []):
if service not in ConfigAdmin.SUPPORTED_SERVICES:
raise ValueError(ERR_UPDATE_UNKNOWN_SERVICE.format(service))
@@ -275,7 +328,7 @@ def update_config(self, **settings):
return ConfigAdmin._for_output(checked_settings)
- def list_periods(self):
+ def list_periods(self) -> dict[Literal["periods"], Any]:
"""
Lists all periods
:return: all configured periods
@@ -285,7 +338,9 @@ def list_periods(self):
ConfigAdmin._for_output(period)
return {"periods": ConfigAdmin._for_output(periods)}
- def get_period(self, name, exception_if_not_exists=True):
+ def get_period(
+ self, name: str, exception_if_not_exists: bool = True
+ ) -> Optional[dict[Literal["period"], Any]]:
"""
Gets a specific period
:param name: name of the period
@@ -293,43 +348,45 @@ def get_period(self, name, exception_if_not_exists=True):
:return:
"""
if name is None or len(name) == 0:
- raise ValueError(ERR_GET_EMPTY_PERIOD_NAME)
+ raise ValueError(ERR_EMPTY_PERIOD_NAME)
period = self._get_period(name)
if period is None:
if exception_if_not_exists:
- raise ValueError(ERR_GET_PERIOD_NOT_FOUND.format(name))
+ raise ValueError(ERR_PERIOD_NOT_FOUND.format(name))
return None
return {"period": ConfigAdmin._for_output(period)}
- def create_period(self, **kwargs):
+ def create_period(self, kwargs: ConfigTablePeriodItem) -> dict[str, Any]:
"""
Creates a new period
:param kwargs: period parameters, see validate_period for allowed parameters
:return: Validated and created period
"""
- period = self._validate_period(**kwargs)
- name = period[configuration.NAME]
+ period = self._validate_period(kwargs)
+ name = period["name"]
if self._get_period(name) is not None:
raise ValueError(ERR_CREATE_PERIOD_EXISTS.format(name))
self._table.put_item(Item=period)
return {"period": ConfigAdmin._for_output(period)}
- def update_period(self, **kwargs):
+ def update_period(self, kwargs: ConfigTablePeriodItem) -> dict[str, Any]:
"""
Updates an existing period
:param kwargs: period data, see validate_period for allowed parameters
:return: validated and updated period
"""
- period = self._validate_period(**kwargs)
- name = period[configuration.NAME]
+ period = self._validate_period(kwargs)
+ name = period["name"]
if name is None or len(name) == 0:
- raise ValueError(ERR_UPDATE_PERIOD_NAME_EMPTY)
+ raise ValueError(ERR_EMPTY_PERIOD_NAME)
if self._get_period(name) is None:
- raise ValueError(ERR_UPDATE_PERIOD_NOT_FOUND.format(name))
+ raise ValueError(ERR_PERIOD_NOT_FOUND.format(name))
self._table.put_item(Item=period)
return {"period": ConfigAdmin._for_output(period)}
- def delete_period(self, name, exception_if_not_exists=False):
+ def delete_period(
+ self, name: str, exception_if_not_exists: bool = False
+ ) -> Optional[dict[Literal["period"], str]]:
"""
Deletes a period. Note that a period can ony be deleted when not longer used in any schedule
:param name: Name of the period
@@ -337,7 +394,7 @@ def delete_period(self, name, exception_if_not_exists=False):
:return:
"""
if name is None or len(name) == 0:
- raise ValueError(ERR_DEL_PERIOD_EMPTY)
+ raise ValueError(ERR_EMPTY_PERIOD_NAME)
# test if period is used in any schedule
schedules_using_period = []
@@ -357,10 +414,10 @@ def delete_period(self, name, exception_if_not_exists=False):
return {"period": name}
else:
if exception_if_not_exists:
- raise ValueError(ERR_DEL_PERIOD_NOT_FOUND.format(name))
+ raise ValueError(ERR_PERIOD_NOT_FOUND.format(name))
return None
- def list_schedules(self):
+ def list_schedules(self) -> dict[Literal["schedules"], Any]:
"""
List all configured schedules
:return: all schedules
@@ -368,7 +425,9 @@ def list_schedules(self):
schedules = self._list_schedules()
return {"schedules": ConfigAdmin._for_output(schedules)}
- def get_schedule(self, name, exception_if_not_exists=True):
+ def get_schedule(
+ self, name: str, exception_if_not_exists: bool = True
+ ) -> Optional[dict[Literal["schedule"], Any]]:
"""
Gets the information for a specific schedule
:param name: name of the schedule
@@ -380,39 +439,45 @@ def get_schedule(self, name, exception_if_not_exists=True):
schedule = self._get_schedule(name)
if schedule is None:
if exception_if_not_exists:
- raise ValueError(ERR_GET_SCHEDULE_NOT_FOUND.format(name))
+ raise ValueError(ERR_SCHEDULE_NOT_FOUND.format(name))
return None
return {"schedule": ConfigAdmin._for_output(schedule)}
- def create_schedule(self, **kwargs):
+ def create_schedule(
+ self, kwargs: ConfigTableScheduleItem
+ ) -> dict[Literal["schedule"], Any]:
"""
Creates a new schedule
:param kwargs: schedule data, see validate_schedule for allowed parameters
:return: Validated data of created schedule
"""
- schedule = self._validate_schedule(**kwargs)
- name = schedule[configuration.NAME]
+ schedule = self._validate_schedule(kwargs)
+ name = schedule["name"]
if self._get_schedule(name) is not None:
raise ValueError(ERR_CREATE_SCHEDULE_EXISTS.format(name))
self._table.put_item(Item=schedule)
return {"schedule": ConfigAdmin._for_output(schedule)}
- def update_schedule(self, **kwargs):
+ def update_schedule(
+ self, kwargs: ConfigTableScheduleItem
+ ) -> dict[Literal["schedule"], Any]:
"""
Updates an existing schedule
:param kwargs: schedule data, see validate_schedule for allowed parameters
:return: Validated updated schedule
"""
- schedule = self._validate_schedule(**kwargs)
- name = schedule[configuration.NAME]
+ schedule = self._validate_schedule(kwargs)
+ name = schedule["name"]
if name is None or len(name) == 0:
raise ValueError(ERR_UPDATE_SCHEDULE_NAME_EMPTY)
if self._get_schedule(name) is None:
- raise ValueError(ERR_UPDATE_SCHEDULE_NOT_FOUND.format(name))
+ raise ValueError(ERR_SCHEDULE_NOT_FOUND.format(name))
self._table.put_item(Item=schedule)
return {"schedule": ConfigAdmin._for_output(schedule)}
- def delete_schedule(self, name, exception_if_not_exists=True):
+ def delete_schedule(
+ self, name: str, exception_if_not_exists: bool = True
+ ) -> Optional[dict[Literal["schedule"], str]]:
"""
Deletes a schedule
:param name: name of the schedule
@@ -423,12 +488,17 @@ def delete_schedule(self, name, exception_if_not_exists=True):
raise ValueError(ERR_DEL_SCHEDULE_NAME_EMPTY)
if self._get_schedule(name) is None:
if exception_if_not_exists:
- raise ValueError(ERR_DEL_SCHEDULE_NOT_FOUND.format(name))
+ raise ValueError(ERR_SCHEDULE_NOT_FOUND.format(name))
return None
self._table.delete_item(Key={"name": name, "type": "schedule"})
return {"schedule": name}
- def get_schedule_usage(self, name, startdate=None, enddate=None):
+ def get_schedule_usage(
+ self,
+ name: str,
+ startdate: Optional[datetime] = None,
+ enddate: Optional[datetime] = None,
+ ) -> Any:
"""
Get running periods for a schedule in a period
:param name: name of the schedule
@@ -442,13 +512,13 @@ def get_schedule_usage(self, name, startdate=None, enddate=None):
schedule = self.configuration.get_schedule(name)
if schedule is None:
- raise ValueError(ERR_GET_USAGE_SCHEDULE_NOT_FOUND.format(name))
+ raise ValueError(ERR_SCHEDULE_NOT_FOUND.format(name))
if startdate:
if not isinstance(startdate, datetime):
try:
start = datetime.strptime(startdate, "%Y%m%d").replace(
- tzinfo=pytz.timezone(schedule.timezone)
+ tzinfo=ZoneInfo(schedule.timezone)
)
except ValueError as ex:
raise ValueError(
@@ -457,14 +527,14 @@ def get_schedule_usage(self, name, startdate=None, enddate=None):
else:
start = startdate
else:
- tz = pytz.timezone(schedule.timezone)
+ tz = ZoneInfo(schedule.timezone)
start = startdate or datetime.now(tz)
if enddate:
if not isinstance(enddate, datetime):
try:
end = datetime.strptime(enddate, "%Y%m%d").replace(
- tzinfo=pytz.timezone(schedule.timezone)
+ tzinfo=ZoneInfo(schedule.timezone)
)
except ValueError as ex:
raise ValueError(
@@ -486,12 +556,12 @@ def get_schedule_usage(self, name, startdate=None, enddate=None):
return ConfigAdmin._for_output(periods)
@staticmethod
- def _for_output(item):
+ def _for_output(item: Any) -> Any:
# to anf from json using custom encoder to convert datetime and set type data into string and lists
return json.loads(json.dumps(item, cls=ConfigAdmin.CustomEncoder))
@staticmethod
- def _ensure_set(s):
+ def _ensure_set(s: list[str] | set[str] | str) -> set[str]:
if isinstance(s, list):
return set(s)
if isinstance(s, str):
@@ -499,13 +569,7 @@ def _ensure_set(s):
return s
@staticmethod
- def _set_as_list(s):
- if isinstance(s, set):
- return list(s)
- return s
-
- @staticmethod
- def _ensure_bool(b):
+ def _ensure_bool(b: Any) -> Optional[bool]:
s = str(b).lower()
if s == "true":
return True
@@ -513,10 +577,10 @@ def _ensure_bool(b):
return False
return None
- def _validate_period(self, **period):
- result = {}
+ def _validate_period(self, period: ConfigTablePeriodItem) -> ConfigTablePeriodItem:
+ result: ConfigTablePeriodItem = {}
- def is_valid_time(s):
+ def is_valid_time(s: Any) -> bool:
return re.match(ConfigAdmin.TIME_REGEX, s) is not None
# allowed and validated parameters
@@ -542,25 +606,25 @@ def is_valid_time(s):
)
# remove None values
- if period[attr] is None or len(str(period[attr])) == 0:
+ if period[attr] is None or len(str(period[attr])) == 0: # type: ignore[literal-required]
continue
# period name
if attr == configuration.NAME:
- result[attr] = period[attr]
+ result[attr] = period[attr] # type: ignore[literal-required]
continue
# description
if attr == configuration.DESCRIPTION:
- result[attr] = period[attr]
+ result[attr] = period[attr] # type: ignore[literal-required]
continue
# validate start and end types times
if attr in [configuration.BEGINTIME, configuration.ENDTIME]:
- time_str = period[attr]
+ time_str = period[attr] # type: ignore[literal-required]
if not is_valid_time(time_str):
raise ValueError(ERR_PERIOD_INVALID_TIME.format(attr, time_str))
- result[attr] = str(
+ result[attr] = str( # type: ignore[literal-required]
datetime.strptime(time_str, configuration.TIME_FORMAT_STRING).time()
)[0 : len(configuration.TIME_FORMAT_STRING)]
if (
@@ -568,17 +632,17 @@ def is_valid_time(s):
and configuration.ENDTIME in result
):
begintime = datetime.strptime(
- result[configuration.BEGINTIME],
+ result["begintime"],
configuration.TIME_FORMAT_STRING,
).time()
endtime = datetime.strptime(
- result[configuration.ENDTIME], configuration.TIME_FORMAT_STRING
+ result["endtime"], configuration.TIME_FORMAT_STRING
).time()
if begintime > endtime:
raise ValueError(
ERR_PERIOD_BEGIN_LATER_THAN_END.format(
- result[configuration.BEGINTIME],
- result[configuration.ENDTIME],
+ result["begintime"],
+ result["endtime"],
)
)
@@ -590,21 +654,20 @@ def is_valid_time(s):
configuration.MONTHDAYS,
configuration.MONTHS,
]:
- temp = self._ensure_set(period[attr])
+ temp = self._ensure_set(period[attr]) # type: ignore[literal-required]
if len(temp) == 0:
continue
# validate month
if attr == configuration.MONTHS:
- # noinspection PyPep8
try:
MonthSetBuilder().build(temp)
- result[attr] = temp
+ result[attr] = temp # type: ignore[literal-required]
continue
- except:
+ except Exception:
raise ValueError(
- ERR_PERIOD_INVALID_MONTHS.format(str(period[attr]))
+ ERR_PERIOD_INVALID_MONTHS.format(str(period[attr])) # type: ignore[literal-required]
)
# validate weekdays
@@ -612,23 +675,22 @@ def is_valid_time(s):
try:
wdb = WeekdaySetBuilder(year=2016, month=12, day=31)
wdb.build(temp)
- result[attr] = temp
+ result[attr] = temp # type: ignore[literal-required]
continue
except Exception as ex:
raise ValueError(
- ERR_PERIOD_INVALID_WEEKDAYS.format(str(period[attr]), ex)
+ ERR_PERIOD_INVALID_WEEKDAYS.format(str(period[attr]), ex) # type: ignore[literal-required]
)
# validate monthdays
if attr == configuration.MONTHDAYS:
- # noinspection PyPep8
try:
MonthdaySetBuilder(year=2016, month=12).build(temp)
- result[attr] = temp
+ result[attr] = temp # type: ignore[literal-required]
continue
- except:
+ except Exception:
raise ValueError(
- ERR_PERIOD_INVALID_MONTHDAYS.format(str(period[attr]))
+ ERR_PERIOD_INVALID_MONTHDAYS.format(str(period[attr])) # type: ignore[literal-required]
)
if configuration.NAME not in result:
@@ -646,13 +708,15 @@ def is_valid_time(s):
else:
raise ValueError(ERR_NO_PERIODS)
- result[ConfigAdmin.TYPE_ATTR] = configuration.PERIOD
+ result["type"] = "period"
return result
# check schedule before writing it to the database
- def _validate_schedule(self, **schedule):
- result = {}
+ def _validate_schedule(
+ self, schedule: ConfigTableScheduleItem
+ ) -> ConfigTableScheduleItem:
+ validated_schedule: ConfigTableScheduleItem = {}
# allowed parameters
valid_parameters = [
@@ -682,18 +746,18 @@ def _validate_schedule(self, **schedule):
)
# skip None values
- if schedule[attr] is None or len(str(schedule[attr])) == 0:
+ if schedule[attr] is None or len(str(schedule[attr])) == 0: # type: ignore[literal-required]
continue
# check periods set
if attr == configuration.PERIODS:
- temp = self._ensure_set(schedule[attr])
+ temp = self._ensure_set(schedule[attr]) # type: ignore[literal-required]
if len(temp) > 0:
- result[attr] = temp
+ validated_schedule[attr] = temp # type: ignore[literal-required]
continue
if attr in [configuration.NAME, configuration.SSM_MAINTENANCE_WINDOW]:
- result[attr] = schedule[attr]
+ validated_schedule[attr] = schedule[attr] # type: ignore[literal-required]
continue
# make sure these fields are valid booleans
@@ -705,12 +769,12 @@ def _validate_schedule(self, **schedule):
configuration.HIBERNATE,
configuration.ENFORCED,
]:
- bool_value = self._ensure_bool(schedule[attr])
+ bool_value = self._ensure_bool(schedule[attr]) # type: ignore[literal-required]
if bool_value is None:
raise ValueError(
- ERR_SCHEDULE_INVALID_BOOLEAN.format(schedule[attr], attr)
+ ERR_SCHEDULE_INVALID_BOOLEAN.format(schedule[attr], attr) # type: ignore[literal-required]
)
- result[attr] = bool_value
+ validated_schedule[attr] = bool_value # type: ignore[literal-required]
continue
# overwrite status, now deprecated, use PROP_OVERRIDE_STATUS instead
@@ -722,15 +786,13 @@ def _validate_schedule(self, **schedule):
)
)
- bool_value = self._ensure_bool(schedule[attr])
+ bool_value = self._ensure_bool(schedule[attr]) # type: ignore[literal-required]
if bool_value is None:
raise ValueError(
- ERR_SCHEDULE_INVALID_BOOLEAN.format(schedule[attr], attr)
+ ERR_SCHEDULE_INVALID_BOOLEAN.format(schedule[attr], attr) # type: ignore[literal-required]
)
- result[configuration.OVERRIDE_STATUS] = (
- configuration.OVERRIDE_STATUS_RUNNING
- if bool_value
- else configuration.OVERRIDE_STATUS_STOPPED
+ validated_schedule["override_status"] = (
+ "running" if bool_value else "stopped"
)
continue
@@ -741,65 +803,81 @@ def _validate_schedule(self, **schedule):
configuration.OVERWRITE, configuration.OVERRIDE_STATUS
)
)
- if schedule[attr] not in configuration.OVERRIDE_STATUS_VALUES:
+ if schedule[attr] not in configuration.OVERRIDE_STATUS_VALUES: # type: ignore[literal-required]
raise ValueError(
ERR_SCHEDULE_INVALID_OVERRIDE.format(
- schedule[attr],
+ schedule[attr], # type: ignore[literal-required]
attr,
",".join(configuration.OVERRIDE_STATUS_VALUES),
)
)
- result[attr] = schedule[attr]
+ validated_schedule[attr] = schedule[attr] # type: ignore[literal-required]
continue
# description
if attr in [configuration.DESCRIPTION, configuration.SCHEDULE_CONFIG_STACK]:
- result[attr] = schedule[attr]
+ validated_schedule[attr] = schedule[attr] # type: ignore[literal-required]
continue
# validate timezone
if attr == configuration.TIMEZONE:
- timezone = schedule[configuration.TIMEZONE]
+ timezone = schedule[configuration.TIMEZONE] # type: ignore[literal-required]
if not SchedulerConfigBuilder.is_valid_timezone(timezone):
raise ValueError(
ERR_SCHEDULE_INVALID_TIMEZONE.format(
timezone, configuration.TIMEZONE
)
)
- result[attr] = timezone
+ validated_schedule[attr] = timezone # type: ignore[literal-required]
# name is mandatory
- if configuration.NAME not in result:
+ if configuration.NAME not in validated_schedule:
raise ValueError(ERR_SCHEDULE_NAME_MISSING)
# if there is no overwrite there must be at least one period
- if configuration.OVERRIDE_STATUS not in schedule:
- if (
- configuration.PERIODS not in schedule
- or len(schedule[configuration.PERIODS]) == 0
- ):
- raise ValueError(ERR_SCHEDULE_NO_PERIOD)
+ if configuration.OVERRIDE_STATUS not in schedule and (
+ configuration.PERIODS not in schedule
+ or len(schedule[configuration.PERIODS]) == 0 # type: ignore[literal-required]
+ ):
+ raise ValueError(ERR_SCHEDULE_NO_PERIOD)
# validate if periods are in configuration
- if configuration.PERIODS in result:
+ if configuration.PERIODS in validated_schedule:
# get list of all configured periods
- periods = [p[configuration.NAME] for p in self._list_periods()]
- for period in result[configuration.PERIODS]:
- if period.split(configuration.INSTANCE_TYPE_SEP)[0] not in periods:
- raise ValueError(ERR_SCHEDULE_PERIOD_DOES_NOT_EXISTS.format(period))
+ periods_from_db = [p[configuration.NAME] for p in self._list_periods()]
- # indicates this s a schedule
- result[ConfigAdmin.TYPE_ATTR] = "schedule"
+ configured_periods = validated_schedule["periods"]
+ if not isinstance(
+ configured_periods, set
+ ): # should be impossible, but mypy cannot currently prove it
+ raise ValueError(
+ "Expected configuration periods to be a string set but received {} instead",
+ type(configured_periods),
+ )
- return result
+ for configured_period in configured_periods:
+ # todo: this behavior of splitting period names to get Instance_type is too widely known and needs
+ # todo: to be centralized somewhere
+ if (
+ configured_period.split(configuration.INSTANCE_TYPE_SEP)[0]
+ not in periods_from_db
+ ):
+ raise ValueError(
+ ERR_SCHEDULE_PERIOD_DOES_NOT_EXISTS.format(configured_period)
+ )
+
+ # indicates this is a schedule
+ validated_schedule["type"] = "schedule"
- def _items_of_type(self, config_type):
+ return validated_schedule
+
+ def _items_of_type(self, config_type: ConfigTableItemType) -> list[Any]:
result = []
args = {"FilterExpression": Key("type").eq(config_type), "ConsistentRead": True}
while True:
- resp = self._table.scan(**args)
+ resp = self._table.scan(**args) # todo: why are we doing a scan here?
result += resp.get("Items", [])
if "LastEvaluatedKey" in resp:
args["ExclusiveStartKey"] = resp["LastEvaluatedKey"]
@@ -808,36 +886,40 @@ def _items_of_type(self, config_type):
return result
- def _list_schedules(self):
+ def _list_schedules(self) -> list[Any]:
return self._items_of_type("schedule")
- def _list_periods(self):
+ def _list_periods(self) -> list[Any]:
return self._items_of_type("period")
- def _get_schedule(self, schedule_name):
+ def _get_schedule(self, schedule_name: str) -> Any:
resp = self._table.get_item(
Key={"name": schedule_name, "type": "schedule"}, ConsistentRead=True
)
return resp.get("Item", None)
- def _get_period(self, period_name):
+ def _get_period(self, period_name: str) -> Any:
resp = self._table.get_item(
Key={"name": period_name, "type": "period"}, ConsistentRead=True
)
return resp.get("Item", None)
def calculate_schedule_usage_for_period(
- self, schedule_name, start_dt, stop_dt=None, logger=None
- ):
+ self,
+ schedule_name: str,
+ start_dt: datetime,
+ stop_dt: Optional[datetime] = None,
+ logger: Optional[Logger] = None,
+ ) -> dict[str, Any]:
result = {}
- def running_seconds(startdt, stopdt):
+ def running_seconds(startdt: datetime, stopdt: datetime) -> int:
return max(int((stopdt - startdt).total_seconds()), 60)
- def running_hours(startdt, stopdt):
+ def running_hours(startdt: datetime, stopdt: datetime) -> int:
return int(((stopdt - startdt).total_seconds() - 1) / 3600) + 1
- def make_period(started_dt, stopped_dt):
+ def make_period(started_dt: Any, stopped_dt: Any) -> dict[str, Any]:
running_period = {
"begin": started_dt,
"end": stopped_dt,
@@ -864,10 +946,10 @@ def make_period(started_dt, stopped_dt):
self._configuration = SchedulerConfigBuilder(logger=self._logger).build(
config_data
)
- conf = configuration.SchedulerConfigBuilder(self._logger).build(
- config=config_data, dt=dt
- )
+ conf = SchedulerConfigBuilder(self._logger).build(config=config_data, dt=dt)
schedule = conf.get_schedule(schedule_name)
+ if schedule is None:
+ raise ValueError
timeline = {dt.replace(hour=0, minute=0)}
for p in schedule.periods:
@@ -889,39 +971,49 @@ def make_period(started_dt, stopped_dt):
running_periods = {}
started = None
starting_period = None
- current_state = None
- inst = as_namedtuple(
- "Instance", {"instance_str": "instance", "allow_resize": False}
+ current_state: Optional[ScheduleState] = None
+ inst = Instance(
+ instance_str="instance",
+ allow_resize=False,
+ id="",
+ hibernate=False,
+ state="",
+ state_name="",
+ is_running=False,
+ is_terminated=False,
+ current_state="stopped",
+ instancetype="",
+ maintenance_window=None,
+ tags={},
+ name="",
+ schedule_name="",
)
for tm in sorted(list(timeline)):
- desired_state, instance_type, period = schedule.get_desired_state(
- inst, self._logger, tm, False
+ desired_state, _, period = schedule.get_desired_state(
+ inst, tm, self._logger, False
)
if current_state != desired_state:
- if desired_state == InstanceSchedule.STATE_RUNNING:
+ if desired_state == "running":
started = tm
- current_state = InstanceSchedule.STATE_RUNNING
+ current_state = "running"
starting_period = period
- elif desired_state == InstanceSchedule.STATE_STOPPED:
+ elif desired_state == "stopped":
stopped = tm
(
desired_state_with_adj_check,
- _,
__,
- ) = schedule.get_desired_state(inst, self._logger, tm, True)
- if (
- desired_state_with_adj_check
- == InstanceSchedule.STATE_RUNNING
- ):
+ ___,
+ ) = schedule.get_desired_state(inst, tm, self._logger, True)
+ if desired_state_with_adj_check == "running":
stopped += timedelta(minutes=1)
- if current_state == InstanceSchedule.STATE_RUNNING:
- current_state = InstanceSchedule.STATE_STOPPED
+ if current_state == "running":
+ current_state = "stopped"
running_periods[starting_period] = make_period(
started, stopped
)
- if current_state == InstanceSchedule.STATE_RUNNING:
+ if current_state == "running":
stopped = dt.replace(hour=23, minute=59) + timedelta(minutes=1)
running_periods[starting_period] = make_period(started, stopped)
diff --git a/source/app/instance_scheduler/configuration/config_dynamodb_adapter.py b/source/app/instance_scheduler/configuration/config_dynamodb_adapter.py
index ccc813a3..089762a5 100644
--- a/source/app/instance_scheduler/configuration/config_dynamodb_adapter.py
+++ b/source/app/instance_scheduler/configuration/config_dynamodb_adapter.py
@@ -1,10 +1,9 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-
from boto3.dynamodb.conditions import Key
-from instance_scheduler.util.dynamodb_utils import DynamoDBUtils
+
from instance_scheduler import configuration
+from instance_scheduler.util.dynamodb_utils import DynamoDBUtils
class ConfigDynamodbAdapter:
diff --git a/source/app/instance_scheduler/configuration/instance_schedule.py b/source/app/instance_scheduler/configuration/instance_schedule.py
index 7f241337..6c461f8a 100644
--- a/source/app/instance_scheduler/configuration/instance_schedule.py
+++ b/source/app/instance_scheduler/configuration/instance_schedule.py
@@ -1,11 +1,19 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-
+from collections.abc import Callable
+from dataclasses import dataclass, field
from datetime import datetime, timedelta
+from typing import Any, ClassVar, Optional, TypedDict
+from zoneinfo import ZoneInfo
-from instance_scheduler import configuration
-import pytz
+from typing_extensions import NotRequired
+
+from instance_scheduler import ScheduleState, configuration
+from instance_scheduler.configuration.running_period import RunningPeriod
+from instance_scheduler.configuration.running_period_dict_element import (
+ RunningPeriodDictElement,
+)
+from instance_scheduler.util.logger import Logger
DEBUG_ACTIVE_PERIOD_IN_SCHEDULE = 'Active period{} in schedule "{}": {}'
DEBUG_NO_RUNNING_PERIODS = 'No running periods at this time found in schedule "{}" for this time, desired state is {}'
@@ -22,78 +30,73 @@
DEBUG_USED_TIME_FOR_SCHEDULE = "Time used to determine desired for instance is {}"
+class Instance(TypedDict):
+ id: str
+ arn: NotRequired[str]
+ allow_resize: bool
+ hibernate: bool
+ state: Any
+ state_name: str
+ is_running: bool
+ is_terminated: bool
+ current_state: ScheduleState
+ instancetype: str
+ engine_type: NotRequired[str]
+ maintenance_window: Optional["InstanceSchedule"]
+ tags: dict[str, str]
+ name: str
+ schedule_name: Optional[str]
+ is_cluster: NotRequired[bool]
+ resized: NotRequired[bool]
+ account: NotRequired[str]
+ region: NotRequired[str]
+ service: NotRequired[str]
+ instance_str: NotRequired[str]
+
+
+class PeriodWithDesiredState(TypedDict):
+ period: RunningPeriod
+ instancetype: Optional[str]
+ state: ScheduleState
+
+
+@dataclass
class InstanceSchedule:
- """
- Implements an instance schedule
- """
-
- STATE_UNKNOWN = "unknown"
- STATE_ANY = "any"
- STATE_STOPPED = "stopped"
- STATE_STOPPED_FOR_RESIZE = "stopped_for_resize"
- STATE_RUNNING = "running"
- STATE_RETAIN_RUNNING = "retain-running"
-
- def __init__(
- self,
- name,
- periods=None,
- timezone=None,
- override_status=None,
- description=None,
- use_metrics=None,
- stop_new_instances=None,
- schedule_dt=None,
- use_maintenance_window=False,
- ssm_maintenance_window=None,
- enforced=False,
- hibernate=False,
- retain_running=False,
- ):
- """
- Initializes a schedule instance
- :param name: Name of a schedule
- :param periods: Periods in which instances are running
- :param timezone: Timezone of the schedule (default = UTC)
- :param override_status: Set to have instances always started or stopped
- :param description: Description of the schedule
- :param use_metrics: Set to true to collect metrics for the schedule
- :param stop_new_instances: Set to True to stop instances that are added to the schema if they are not in a running period
- :param schedule_dt: datetime to use for scheduling
- :param use_maintenance_window: Set to True to use the maintenance window as an additional schedule in
- which instances are running
- :param ssm_maintenance_window: name of ssm mainatenance window in which to start ec2 instances
- :param enforced: start/stop state of the schema on instances
- :param: hibernate: hibernate instances when stopping
- """
- self.name = name
- self.periods = periods
- self.timezone = timezone
- self.override_status = override_status
- self.description = description
- self.stop_new_instances = stop_new_instances
- self.use_maintenance_window = use_maintenance_window
- self.ssm_maintenance_window = ssm_maintenance_window
- self.use_metrics = use_metrics
- self.enforced = enforced
- self.hibernate = hibernate
- self.retain_running = retain_running
- self.schedule_dt = (
- schedule_dt
- if schedule_dt is not None
- else datetime.now(pytz.timezone(self.timezone))
- )
- self._logger = None
-
- def _log_info(self, msg, *args):
- if self._logger is not None:
- self._logger.info(msg, *args)
-
- def _log_debug(self, msg, *args):
+ STATE_UNKNOWN: ClassVar[str] = "unknown"
+ STATE_ANY: ClassVar[str] = "any"
+ STATE_STOPPED: ClassVar[str] = "stopped"
+ STATE_STOPPED_FOR_RESIZE: ClassVar[str] = "stopped_for_resize"
+ STATE_RUNNING: ClassVar[str] = "running"
+ STATE_RETAIN_RUNNING: ClassVar[str] = "retain-running"
+
+ # todo: reduce the number of optionals here, it complicates all downstream dependencies
+ name: str
+ periods: list[RunningPeriodDictElement] = field(default_factory=list)
+ # todo: UTC was defined as the default in the original comments but we need to confirm
+ # exactly how default tz is loaded from cfn input parameters, test it, and then decide if we should remove this
+ # fallback entirely
+ timezone: str = "UTC"
+ override_status: Optional[str] = None
+ description: Optional[str] = None
+ use_metrics: Optional[bool] = None
+ stop_new_instances: Optional[bool] = None
+ use_maintenance_window: Optional[bool] = False
+ ssm_maintenance_window: Optional[str] = None
+ enforced: Optional[bool] = False
+ hibernate: Optional[bool] = False
+ retain_running: Optional[bool] = False
+ # todo: this value is loaded in global_config but is not respected by scheduling_context.
+ # when these are unified, this may be a behavioral change to consider
+ configured_in_stack: Optional[str] = None
+
+ def __post_init__(self) -> None:
+ self._logger: Optional[Logger] = None
+
+ def _log_debug(self, msg: str, *args: Optional[str]) -> None:
if self._logger is not None:
self._logger.debug(msg, *args)
- def __str__(self):
+ def __str__(self) -> str:
s = 'Schedule "{}": '.format(self.name)
attributes = []
if self.description:
@@ -155,26 +158,33 @@ def __str__(self):
return s
def get_desired_state(
- self, instance, logger=None, dt=None, check_adjacent_periods=True
- ):
+ self,
+ instance: Instance,
+ dt: datetime,
+ logger: Optional[Logger] = None,
+ check_adjacent_periods: bool = True,
+ ) -> tuple[ScheduleState, Optional[str], Optional[str]]:
"""
Test if an instance should be running at a specific moment in this schedule
:param instance: the instance to test
:param logger: logger for logging output of scheduling logic
- :param dt: date time to use for scheduling, use None for using the time specified in the constructor of the schedule
+ :param dt: date time to use for scheduling, THIS MUST BE A TIMEZONE-AWARE DATETIME
:param check_adjacent_periods: check for adjacent periods in a schedule
:return: desired state, instance type and name of the active period of the schedule if the state is running
"""
# gets the local time using the configured timezone
- def get_check_time(time):
- check_time = time if time else self.schedule_dt
- return check_time.astimezone(pytz.timezone(self.timezone))
+ def get_check_time(time: datetime) -> datetime:
+ return time.astimezone(ZoneInfo(self.timezone))
# actions for desired state is running
- def handle_running_state(inst, periods):
+ def handle_running_state(
+ inst: Instance, periods: list[PeriodWithDesiredState]
+ ) -> tuple[ScheduleState, Optional[str], str]:
# used to determining most nearest period if more than one period returns a running state in a schedule
- def latest_starttime(p1, p2):
+ def latest_starttime(
+ p1: PeriodWithDesiredState, p2: PeriodWithDesiredState
+ ) -> PeriodWithDesiredState:
if p1["period"].begintime is None:
return p2
if p2["period"].begintime is None:
@@ -182,16 +192,24 @@ def latest_starttime(p1, p2):
return p1 if p1["period"].begintime > p2["period"].begintime else p2
# test if we need to change the type of the instance
- def requires_adjust_instance_size(desired_instance_type, checked_instance):
+ def requires_adjust_instance_size(
+ desired_instance_type: Optional[str], checked_instance: Instance
+ ) -> bool:
return (
- checked_instance.allow_resize
+ checked_instance["allow_resize"]
and desired_instance_type is not None
- and checked_instance.is_running
- and desired_instance_type != checked_instance.instancetype
+ and checked_instance["is_running"]
+ and desired_instance_type != checked_instance["instancetype"]
)
# reduce is removed from python3, replace by minimal implementation for python3 compatibility
- def _reduce(fn, items):
+ def _reduce(
+ fn: Callable[
+ [PeriodWithDesiredState, PeriodWithDesiredState],
+ PeriodWithDesiredState,
+ ],
+ items: list[PeriodWithDesiredState],
+ ) -> Optional[PeriodWithDesiredState]:
if items is None or len(list(items)) == 0:
return None
else:
@@ -205,6 +223,11 @@ def _reduce(fn, items):
# nearest period in schedule with running state
current_running_period = _reduce(latest_starttime, periods)
+ if not current_running_period:
+ raise ValueError(
+ "Tried to find the latest start time of an empty list of periods"
+ )
+
multiple_active_periods = len(list(periods)) > 1
self._log_debug(
@@ -219,41 +242,41 @@ def _reduce(fn, items):
DEBUG_USED_PERIOD.format(current_running_period["period"].name)
)
- desired_state = InstanceSchedule.STATE_RUNNING
- desired_type = (
- current_running_period["instancetype"] if inst.allow_resize else None
+ desired_state: ScheduleState = "running"
+ desired_type: Optional[str] = (
+ current_running_period["instancetype"] if inst["allow_resize"] else None
)
# check if the instance type matches the desired type, if not set the status to stopped if the instance is currently
# and the instance will be started with the desired type at the next invocation
if requires_adjust_instance_size(desired_type, inst):
- desired_state = InstanceSchedule.STATE_STOPPED_FOR_RESIZE
+ desired_state = "stopped_for_resize"
self._log_debug(
DEBUG_SET_DESIRED_INSTANCE_TYPE,
- inst.instancetype,
+ inst["instancetype"],
desired_type,
desired_state,
)
return desired_state, desired_type, current_running_period["period"].name
# actions for desired state is any state
- def handle_any_state():
- desired_state = InstanceSchedule.STATE_ANY
+ def handle_any_state() -> tuple[ScheduleState, None, None]:
+ desired_state: ScheduleState = "any"
self._log_debug(DEBUG_STATE_ANY, self.name, desired_state)
return desired_state, None, None
# actions for desired state is stopped
- def handle_stopped_state():
- desired_state = InstanceSchedule.STATE_STOPPED
+ def handle_stopped_state() -> tuple[ScheduleState, None, None]:
+ desired_state: ScheduleState = "stopped"
self._log_debug(DEBUG_NO_RUNNING_PERIODS, self.name, desired_state)
return desired_state, None, None
# actions if there is an override value set for the schema
- def handle_override_status():
- desired_state = (
- InstanceSchedule.STATE_RUNNING
+ def handle_override_status() -> tuple[ScheduleState, None, str]:
+ desired_state: ScheduleState = (
+ "running"
if self.override_status == configuration.OVERRIDE_STATUS_RUNNING
- else InstanceSchedule.STATE_STOPPED
+ else "stopped"
)
self._log_debug(DEBUG_OVERRIDE_STATUS, self.override_status, desired_state)
return desired_state, None, "override_status"
@@ -276,16 +299,14 @@ def handle_override_status():
# get periods from the schema that have a running state
periods_with_running_state = [
- p
- for p in periods_with_desired_states
- if p["state"] == InstanceSchedule.STATE_RUNNING
+ p for p in periods_with_desired_states if p["state"] == "running"
]
if any(periods_with_running_state):
return handle_running_state(instance, periods_with_running_state)
period_with_any_state = filter(
- lambda period: period["state"] == InstanceSchedule.STATE_ANY,
+ lambda period: period["state"] == "any",
periods_with_desired_states,
)
if any(period_with_any_state):
@@ -299,7 +320,7 @@ def handle_override_status():
for p in self.get_periods_with_desired_states(
localized_time - timedelta(minutes=1)
)
- if p["state"] == InstanceSchedule.STATE_RUNNING
+ if p["state"] == "running"
]
self._log_debug(
"Running period(s) for previous minute {}",
@@ -312,7 +333,7 @@ def handle_override_status():
for p in self.get_periods_with_desired_states(
localized_time + timedelta(minutes=1)
)
- if p["state"] == InstanceSchedule.STATE_RUNNING
+ if p["state"] == "running"
]
self._log_debug(
"Running period(s) for next minute {}",
@@ -326,8 +347,10 @@ def handle_override_status():
return handle_stopped_state()
- def get_periods_with_desired_states(self, time):
- periods_with_desired_states = [
+ def get_periods_with_desired_states(
+ self, time: datetime
+ ) -> list[PeriodWithDesiredState]:
+ periods_with_desired_states: list[PeriodWithDesiredState] = [
{
"period": p["period"],
"instancetype": p.get("instancetype", None),
diff --git a/source/app/instance_scheduler/configuration/running_period.py b/source/app/instance_scheduler/configuration/running_period.py
index b177fc86..4c96909c 100644
--- a/source/app/instance_scheduler/configuration/running_period.py
+++ b/source/app/instance_scheduler/configuration/running_period.py
@@ -1,12 +1,12 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
+from dataclasses import dataclass
+from datetime import datetime, time
+from typing import Literal, Optional
-
-import datetime
-
-from instance_scheduler import configuration
-from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler import ScheduleState, configuration
from instance_scheduler.util.display_helper import set_str, time_str
+from instance_scheduler.util.logger import Logger
DEBUG_CHECK_DT_START_TIME = "{} Time {} is {} starttime {}, returned state is {}"
DEBUG_CHECK_DT_START_AND_STOP = "{} Time {} is {} {}-{}, returned state is {}"
@@ -18,34 +18,19 @@
DEBUG_CHECK_WEEKDAYS = '{} Weekday "{}" {}in weekdays ({})'
+@dataclass
class RunningPeriod:
- def __init__(
- self,
- name,
- begintime=None,
- endtime=None,
- weekdays=None,
- months=None,
- monthdays=None,
- ):
- """
- Defines a period in which an instance should be running
- :param name: name of the period
- :param begintime: begin time of the period (time)
- :param endtime: end time of the period (time)
- :param weekdays: weekdays (set 0..6)
- :param months: months of the period (set 1..12)
- :param monthdays: days in the month (set 1..28-31)
- """
- self.name = name
- self.begintime = begintime
- self.endtime = endtime
- self.weekdays = weekdays
- self.months = months
- self.monthdays = monthdays
- self._logger = None
-
- def __str__(self):
+ name: str
+ begintime: Optional[time] = None
+ endtime: Optional[time] = None
+ weekdays: Optional[set[int]] = None
+ months: Optional[set[int]] = None
+ monthdays: Optional[set[int]] = None
+
+ def __post_init__(self) -> None:
+ self._logger: Optional[Logger] = None
+
+ def __str__(self) -> str:
s = 'Period "{}": '.format(self.name)
conditions = []
if self.begintime:
@@ -70,15 +55,13 @@ def __str__(self):
return s
- def _log_debug(self, msg, *args):
+ def _log_debug(self, msg: str, *args: str) -> None:
if self._logger is not None:
self._logger.debug(msg, *args)
- def _log_info(self, msg, *args):
- if self._logger is not None:
- self._logger.info(msg, *args)
-
- def get_desired_state(self, logger, current_dt):
+ def get_desired_state(
+ self, logger: Optional[Logger], current_dt: datetime
+ ) -> ScheduleState:
"""
Test if the instance should be running at the specified dt, all conditions configured a period should be true
:param logger: logger to log the output of scheduling logic
@@ -86,30 +69,32 @@ def get_desired_state(self, logger, current_dt):
:return: desired state for the instance in the period
"""
- def state_str(checked):
+ def state_str(checked: bool) -> Literal["[running]", "[stopped]"]:
return "[running]" if checked else "[stopped]"
- def check_running_state_str(checked_state):
- return state_str(checked_state != InstanceSchedule.STATE_STOPPED)
+ def check_running_state_str(
+ checked_state: str,
+ ) -> Literal["[running]", "[stopped]"]:
+ return state_str(checked_state != "stopped")
- def not_str(is_not_not):
+ def not_str(is_not_not: bool) -> str:
return "" if is_not_not else "not "
# check day of month
- def check_monthday(dt):
+ def check_monthday(dt: datetime) -> bool:
result = self.monthdays is None or dt.day in self.monthdays
if self.monthdays:
self._log_debug(
DEBUG_CHECK_MONTH_DAY,
state_str(result),
- dt.day,
+ str(dt.day),
"" if result else "not ",
set_str(self.monthdays),
)
return result
# check month
- def check_month(dt):
+ def check_month(dt: datetime) -> bool:
result = self.months is None or dt.month in self.months
if self.months:
self._log_debug(
@@ -124,7 +109,7 @@ def check_month(dt):
return result
# check weekday
- def check_weekday(dt):
+ def check_weekday(dt: datetime) -> bool:
result = self.weekdays is None or dt.weekday() in self.weekdays
if self.weekdays is not None:
self._log_debug(
@@ -137,31 +122,25 @@ def check_weekday(dt):
return result
# check time
- def check_time(dt):
- t = datetime.time(dt.hour, dt.minute, dt.second)
+ def check_time(dt: datetime) -> ScheduleState:
+ t = time(dt.hour, dt.minute, dt.second)
ts = time_str(t)
# no start and stop time, means running all day
if self.begintime is None and self.endtime is None:
- desired_state = InstanceSchedule.STATE_RUNNING
+ desired_state: ScheduleState = "running"
self._log_debug(
DEBUG_CHECK_DT_UNDEFINED_START_STOP, state_str(True), desired_state
)
return desired_state
- elif self.begintime is None:
+ elif self.begintime is None and self.endtime is not None:
# just the end time, stopped if later than that time
- desired_state = (
- InstanceSchedule.STATE_STOPPED
- if t >= self.endtime
- else InstanceSchedule.STATE_ANY
- )
+ desired_state = "stopped" if t >= self.endtime else "any"
self._log_debug(
DEBUG_CHECK_DT_STOP_TIME,
check_running_state_str(desired_state),
ts,
- "before"
- if desired_state == InstanceSchedule.STATE_ANY
- else "after",
+ "before" if desired_state == "any" else "after",
time_str(self.endtime),
desired_state,
)
@@ -169,47 +148,41 @@ def check_time(dt):
elif self.begintime is not None and self.endtime is None:
# just the start time, running if later that that time
- desired_state = (
- InstanceSchedule.STATE_RUNNING
- if t >= self.begintime
- else InstanceSchedule.STATE_ANY
- )
+ desired_state = "running" if t >= self.begintime else "any"
self._log_debug(
DEBUG_CHECK_DT_START_TIME,
check_running_state_str(desired_state),
ts,
- "before"
- if desired_state == InstanceSchedule.STATE_ANY
- else "after",
+ "before" if desired_state == "any" else "after",
time_str(self.begintime),
desired_state,
)
return desired_state
- else:
+ elif self.begintime is not None and self.endtime is not None:
# start and stop time, test if time falls in the period defined by these times
desired_state = (
- InstanceSchedule.STATE_RUNNING
- if self.begintime <= t < self.endtime
- else InstanceSchedule.STATE_STOPPED
+ "running" if self.begintime <= t < self.endtime else "stopped"
)
self._log_debug(
DEBUG_CHECK_DT_START_AND_STOP,
check_running_state_str(desired_state),
ts,
- "within"
- if desired_state == InstanceSchedule.STATE_RUNNING
- else "outside",
+ "within" if desired_state == "running" else "outside",
time_str(self.begintime),
time_str(self.endtime),
desired_state,
)
+ else:
+ assert False, "unreachable"
+ # the above defines all 4 possible combinations of none/not_none on begintime and endtime
+ # so this should be impossible to reach
return desired_state
self._logger = logger
- state = InstanceSchedule.STATE_STOPPED
+ state: ScheduleState = "stopped"
self._log_debug(DEBUG_CHECK_DT, self.name)
for check in [check_weekday, check_month, check_monthday]:
diff --git a/source/app/instance_scheduler/configuration/running_period_dict_element.py b/source/app/instance_scheduler/configuration/running_period_dict_element.py
new file mode 100644
index 00000000..692dba7c
--- /dev/null
+++ b/source/app/instance_scheduler/configuration/running_period_dict_element.py
@@ -0,0 +1,12 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from typing import Optional, TypedDict
+
+from typing_extensions import NotRequired
+
+from instance_scheduler.configuration.running_period import RunningPeriod
+
+
+class RunningPeriodDictElement(TypedDict):
+ period: RunningPeriod
+ instancetype: NotRequired[Optional[str]]
diff --git a/source/app/instance_scheduler/configuration/scheduler_config.py b/source/app/instance_scheduler/configuration/scheduler_config.py
index 706aefc1..a3e63fa5 100644
--- a/source/app/instance_scheduler/configuration/scheduler_config.py
+++ b/source/app/instance_scheduler/configuration/scheduler_config.py
@@ -1,12 +1,14 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-
import copy
import os
-from datetime import datetime
+from datetime import datetime, timezone
+from typing import Any, Optional
+from zoneinfo import ZoneInfo
from instance_scheduler import configuration
+from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler.configuration.scheduling_context import TagTemplate
# class to hold the configuration for the instance scheduler
INF_SCHEDULE_DISPLAY = (
@@ -33,32 +35,32 @@
TAG_VAL_STR = "{{{}}}"
-class SchedulerConfig:
+class GlobalConfig:
"""
Implements scheduler configuration
"""
def __init__(
self,
- scheduled_services,
- schedule_clusters,
- tag_name,
- regions,
- default_timezone,
- schedules,
- trace,
- enable_SSM_maintenance_windows,
- use_metrics,
- remote_account_ids,
- namespace,
- aws_partition,
- scheduler_role_name,
- organization_id,
- schedule_lambda_account,
- create_rds_snapshot,
- started_tags=None,
- stopped_tags=None,
- ):
+ scheduled_services: list[str],
+ schedule_clusters: bool,
+ tag_name: str,
+ regions: list[str],
+ default_timezone: ZoneInfo,
+ schedules: dict[str, InstanceSchedule],
+ trace: bool,
+ enable_ssm_maintenance_windows: bool,
+ use_metrics: bool,
+ remote_account_ids: list[str],
+ namespace: str,
+ aws_partition: str,
+ scheduler_role_name: str,
+ organization_id: str,
+ schedule_lambda_account: bool,
+ create_rds_snapshot: bool,
+ started_tags: str = "",
+ stopped_tags: str = "",
+ ) -> None:
"""
Initializes schedule configuration instance
:param scheduled_services: services handled by the scheduler
@@ -68,7 +70,7 @@ def __init__(
:param default_timezone: default timezone for schedules
:param schedules: instance running schedules
:param trace: set to true for detailed logging
- :param enable_SSM_maintenance_windows: set to true for enable solution to retrieve SSM Maintenance Windows.
+ :param enable_ssm_maintenance_windows: set to true for enable solution to retrieve SSM Maintenance Windows.
:param use_metrics: global flag to enable metrics collection
:param remote_account_ids: remote account ids
:param namespace: namespace for the stack
@@ -84,7 +86,7 @@ def __init__(
self.schedules = schedules
self.default_timezone = default_timezone
self.trace = trace
- self.enable_SSM_maintenance_windows = enable_SSM_maintenance_windows
+ self.enable_ssm_maintenance_windows = enable_ssm_maintenance_windows
self.use_metrics = use_metrics
self.regions = regions
self.remote_account_ids = remote_account_ids
@@ -108,7 +110,7 @@ def __init__(
else self.tag_list(self.build_tags_from_template(stopped_tags))
)
- def get_schedule(self, name):
+ def get_schedule(self, name: str) -> Optional[InstanceSchedule]:
"""
Get a schedule by its name
:param name: name of the schedule
@@ -117,7 +119,9 @@ def get_schedule(self, name):
return self.schedules[name] if name in self.schedules else None
@classmethod
- def build_tags_from_template(cls, tags_str, tag_variables=None):
+ def build_tags_from_template(
+ cls, tags_str: Any, tag_variables: Optional[Any] = None
+ ) -> dict[str, str]:
lastkey = None
tags = {}
for tag in tags_str.split(","):
@@ -130,7 +134,7 @@ def build_tags_from_template(cls, tags_str, tag_variables=None):
tag_vars = {} if tag_variables is None else copy.copy(tag_variables)
- dt = datetime.utcnow()
+ dt = datetime.now(timezone.utc)
tag_vars.update(
{
configuration.TAG_VAL_SCHEDULER: os.getenv(configuration.ENV_STACK, ""),
@@ -151,27 +155,18 @@ def build_tags_from_template(cls, tags_str, tag_variables=None):
return tags
@classmethod
- def tag_list(cls, tags_dict):
- valid_tags = {
- tag_key: tags_dict[tag_key]
- for tag_key in tags_dict
- if not (tag_key.startswith("aws:") or tag_key.startswith("cloudformation:"))
- }
- return (
- [{"Key": t, "Value": tags_dict[t]} for t in tags_dict]
- if valid_tags is not None
- else []
- )
+ def tag_list(cls, tags_dict: dict[str, str]) -> list[TagTemplate]:
+ return [{"Key": t, "Value": tags_dict[t]} for t in tags_dict]
- def __str__(self):
+ def __str__(self) -> str:
s = INF_SCHEDULE_DISPLAY.format(
", ".join(self.scheduled_services),
str(self.schedule_clusters),
str(self.create_rds_snapshot),
self.tag_name,
- self.default_timezone,
+ str(self.default_timezone),
str(self.trace),
- str(self.enable_SSM_maintenance_windows),
+ str(self.enable_ssm_maintenance_windows),
str(self.use_metrics),
", ".join(self.regions),
str(self.started_tags),
diff --git a/source/app/instance_scheduler/configuration/scheduler_config_builder.py b/source/app/instance_scheduler/configuration/scheduler_config_builder.py
index 4960b661..79c54c69 100644
--- a/source/app/instance_scheduler/configuration/scheduler_config_builder.py
+++ b/source/app/instance_scheduler/configuration/scheduler_config_builder.py
@@ -1,19 +1,18 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-
import datetime
+import re as regex
import time
+import zoneinfo
+from typing import TYPE_CHECKING, Any, Optional
+from zoneinfo import ZoneInfo
-import dateutil.parser
+from boto3.session import Session
-from instance_scheduler import configuration
-import pytz
-import re as regex
-from instance_scheduler import boto_retry
+from instance_scheduler import boto_retry, configuration
from instance_scheduler.configuration.instance_schedule import InstanceSchedule
from instance_scheduler.configuration.running_period import RunningPeriod
-from instance_scheduler.configuration.scheduler_config import SchedulerConfig
+from instance_scheduler.configuration.scheduler_config import GlobalConfig
from instance_scheduler.configuration.setbuilders.month_setbuilder import (
MonthSetBuilder,
)
@@ -23,52 +22,21 @@
from instance_scheduler.configuration.setbuilders.weekday_setbuilder import (
WeekdaySetBuilder,
)
+from instance_scheduler.util.app_env import get_app_env
+from instance_scheduler.util.logger import Logger
+
+if TYPE_CHECKING:
+ from mypy_boto3_ssm.client import SSMClient
+else:
+ SSMClient = object
REGEX_SSM_PARAM = "{param:(.+?)}"
-ATTR_BEGINTIME = "begintime"
-ATTR_REMOTE_ACCOUNT_IDS = "remote_account_ids"
-ATTR_ORGANIZATION_ID = "organization_id"
-ATTR_NAMESPACE = "namespace"
-ATTR_SCHEDULER_ROLE_NAME = "scheduler_role_name"
-ATTR_CREATE_RDS_SNAPSHOT = "create_rds_snapshot"
-ATTR_DEFAULT_TIMEZONE = "default_timezone"
-ATTR_AWS_PARTITION = "aws_partition"
-ATTR_ENDTIME = "endtime"
-ATTR_ENFORCED = "enforced"
-ATTR_HIBERNATE = "hibernate"
-ATTR_INSTANCE_TYPE = "instancetype"
-ATTR_MONTHDAYS = "monthdays"
-ATTR_MONTHS = "months"
-ATTR_NAME = "name"
-ATTR_OVERRIDE_STATUS = "override_status"
-ATTR_PERIOD = "period"
-ATTR_PERIODS = "periods"
-ATTR_REGIONS = "regions"
-ATTR_RETAIN_RUNNING = "retain_running"
-ATTR_SCHEDULE_DT = "schedule_dt"
-ATTR_SCHEDULE_LAMBDA_ACCOUNT = "schedule_lambda_account"
-ATTR_SCHEDULED_SERVICES = "scheduled_services"
-ATTR_SCHEDULE_CLUSTERS = "schedule_clusters"
-ATTR_SCHEDULES = "schedules"
-ATTR_STARTED_TAGS = "started_tags"
-ATTR_STOP_NEW_INSTANCES = "stop_new_instances"
-ATTR_STOPPED_TAGS = "stopped_tags"
-ATTR_TAGNAME = "tag_name"
-ATTR_TIMEZONE = "timezone"
-ATTR_TRACE = "trace"
-ATTR_ENABLE_SSM_MAINTENANCE_WINDOWS = "enable_SSM_maintenance_windows"
-ATTR_USE_MAINTENANCE_WINDOW = "use_maintenance_window"
-ATTR_SSM_MAINTENANCE_WINDOW = "ssm_maintenance_window"
-ATTR_USE_METRICS = "use_metrics"
-ATTR_WEEKDAYS = "weekdays"
MSG_BEGIN_MUST_BEFORE_END = "Begin time {} must be earlier than end time in {}"
MSG_DUPLICATE_PERIOD_NAME_FOUND = 'Duplicate period name "{}" found'
MSG_DUPLICATE_SCHEDULE_NAME_FOUND = 'Duplicate schedule name "{}" found'
-MSG_INVALID_DEFAULT_TIMEZONE = (
- '"{}" is not a valid timezone, use pytz.all_timezones to list all valid zones'
-)
+MSG_INVALID_DEFAULT_TIMEZONE = '"{}" is not a valid timezone, use zoneinfo.available_timezones() to list all valid zones'
MSG_INVALID_OVERRIDE_STATUS = "{} is not a valid value for {}, possible values are {}"
MSG_NAME_MISSING_IN_PERIOD = 'Name missing in period "{}"'
MSG_NAME_MISSING_IN_SCHEDULE = "Name missing in schedule {}"
@@ -76,7 +44,7 @@
MSG_SCHEDULE_IS_NOT_DEFINED = 'Period "{}" used in schedule "{}" is not defined'
MSG_TAGNAME_MISSING_IN_CONFIGURATION = "tagname is missing in configuration"
MSG_INVALID_SCHEDULE_TIMEZONE = (
- '"{}" is in schedule config "{}" is not a valid timezone, check pytz.all_timezone for '
+ '"{}" is in schedule config "{}" is not a valid timezone, check zoneinfo.available_timezones() for '
"valid zones"
)
@@ -86,37 +54,24 @@ class SchedulerConfigBuilder:
Class that implements logic for building the configuration from the raw stored configuration data.
"""
- _checked_timezones = dict()
- _invalid_timezones = set()
- _all_timezones = {tz.lower(): tz for tz in pytz.all_timezones}
+ _checked_timezones: dict[str, Any] = dict()
+ _invalid_timezones: set[str] = set()
+ _all_timezones = {tz.lower(): tz for tz in zoneinfo.available_timezones()}
- def __init__(self, logger):
+ def __init__(self, logger: Optional[Logger]) -> None:
self._logger = logger
- self._config = None
- self._ssm = None
+ self._config: Any = None
+ self._ssm: Optional[SSMClient] = None
@property
- def ssm(self):
+ def ssm(self) -> SSMClient:
if self._ssm is None:
self._ssm = boto_retry.get_client_with_standard_retry("ssm")
return self._ssm
- def build(self, config, dt=None):
- def get_scheduler_tagname(config_data):
- name = config_data.get(configuration.TAGNAME, configuration.DEFAULT_TAGNAME)
- if not name or len(name) == 0:
- raise ValueError(MSG_TAGNAME_MISSING_IN_CONFIGURATION)
- return name
-
- def get_default_timezone(config_data):
- tz = config_data.get(
- configuration.DEFAULT_TIMEZONE, configuration.DEFAULT_TZ
- )
- validated = SchedulerConfigBuilder.validated_timezone(tz)
- if validated is None:
- raise ValueError(MSG_INVALID_DEFAULT_TIMEZONE.format(tz))
- return validated
-
+ def build(
+ self, config: dict[Any, Any], dt: Optional[datetime.datetime] = None
+ ) -> GlobalConfig:
self._config = config
config_date = dt if dt is not None else datetime.datetime.now()
@@ -126,39 +81,42 @@ def get_default_timezone(config_data):
remote_account_ids_from_ssm = self.get_remote_account_ids_from_ssm(config)
- return SchedulerConfig(
- scheduled_services=config.get(configuration.SCHEDULED_SERVICES, [])
- or [],
- schedule_clusters=config.get(configuration.SCHEDULE_CLUSTERS, False),
- create_rds_snapshot=config.get(configuration.CREATE_RDS_SNAPSHOT, True),
- tag_name=get_scheduler_tagname(config),
- regions=config.get(configuration.REGIONS, []) or [],
- default_timezone=get_default_timezone(config),
+ app_env = get_app_env()
+
+ session = Session()
+ aws_partition = session.get_partition_for_region(session.region_name)
+
+ return GlobalConfig(
+ scheduled_services=app_env.scheduled_services(),
+ schedule_clusters=app_env.enable_rds_clusters,
+ create_rds_snapshot=app_env.enable_rds_snapshots,
+ tag_name=app_env.schedule_tag_key,
+ regions=app_env.schedule_regions,
+ default_timezone=app_env.default_timezone,
schedules=self._build_schedules(
- config, get_default_timezone(config), scheduler_metrics, config_date
+ config,
+ str(app_env.default_timezone),
+ scheduler_metrics,
+ config_date,
),
- trace=config.get(configuration.TRACE, False),
- enable_SSM_maintenance_windows=config.get(
- configuration.ENABLE_SSM_MAINTENANCE_WINDOWS, False
- ),
- use_metrics=scheduler_metrics,
+ trace=app_env.enable_debug_logging,
+ enable_ssm_maintenance_windows=app_env.enable_ec2_ssm_maintenance_windows,
+ use_metrics=app_env.enable_cloudwatch_metrics,
remote_account_ids=remote_account_ids_from_ssm,
- aws_partition=config.get(configuration.AWS_PARTITION, ""),
- namespace=config.get(configuration.NAMESPACE, ""),
- scheduler_role_name=config.get(configuration.SCHEDULER_ROLE_NAME, ""),
+ aws_partition=aws_partition,
+ namespace=app_env.app_namespace,
+ scheduler_role_name=app_env.scheduler_role_name,
organization_id=config.get(configuration.ORGANIZATION_ID, ""),
- schedule_lambda_account=config.get(
- configuration.SCHEDULE_LAMBDA_ACCOUNT, True
- ),
- started_tags=config.get(configuration.STARTED_TAGS, ""),
- stopped_tags=config.get(configuration.STOPPED_TAGS, ""),
+ schedule_lambda_account=app_env.enable_schedule_hub_account,
+ started_tags=",".join(app_env.start_tags),
+ stopped_tags=",".join(app_env.stop_tags),
)
except ValueError as ex:
if self._logger is not None:
self._logger.error(str(ex))
- return None
+ raise ex
- def get_remote_account_ids_from_ssm(self, config):
+ def get_remote_account_ids_from_ssm(self, config: dict[Any, Any]) -> list[str]:
remote_account_ids_from_ssm = []
for account_id in config.get(configuration.REMOTE_ACCOUNT_IDS, []) or []:
if regex.match(REGEX_SSM_PARAM, account_id):
@@ -175,7 +133,13 @@ def get_remote_account_ids_from_ssm(self, config):
return remote_account_ids_from_ssm
# build the schedules from the configuration
- def _build_schedules(self, conf, dflt_tz, scheduler_use_metrics, dt):
+ def _build_schedules(
+ self,
+ conf: Any,
+ dflt_tz: str,
+ scheduler_use_metrics: bool,
+ dt: datetime.datetime,
+ ) -> dict[str, InstanceSchedule]:
schedules = {}
# use the periods to build the schedules that can be assigned to the instances
@@ -194,9 +158,15 @@ def _build_schedules(self, conf, dflt_tz, scheduler_use_metrics, dt):
return schedules
- def _build_schedule(self, schedule_config, dflt_tz, scheduler_use_config, dt):
+ def _build_schedule(
+ self,
+ schedule_config: Any,
+ dflt_tz: str,
+ scheduler_use_config: bool,
+ dt: datetime.datetime,
+ ) -> Optional[InstanceSchedule]:
# gets the timezone
- def get_timezone(schedule_configuration):
+ def get_timezone(schedule_configuration: Any) -> str:
schedule_timezone = schedule_configuration.get(configuration.TIMEZONE)
if not schedule_timezone:
schedule_timezone = dflt_tz
@@ -280,6 +250,7 @@ def get_override_status(config):
enforced=schedule_config.get(configuration.ENFORCED, False),
hibernate=schedule_config.get(configuration.HIBERNATE, False),
retain_running=schedule_config.get(configuration.RETAINED_RUNNING),
+ configured_in_stack=schedule_config.get("configured_in_stack", None),
)
except ValueError as ex:
@@ -320,7 +291,7 @@ def get_config_for_period(period_name):
return schedule_periods
@staticmethod
- def get_time_from_string(timestr):
+ def get_time_from_string(timestr: str) -> Optional[datetime.time]:
"""
Standardised method to build time object instance from time string
:param timestr: string in format as defined in configuration.TIME_FORMAT_STRING
@@ -390,205 +361,7 @@ def build_period_config_set(period_config, set_builder, config_name):
)
@staticmethod
- def configuration_from_dict(d):
- """
- This method builds a configuration object instance that is passed as a dictionary in the event of a lambda function
- :param d:
- :return:
- """
-
- config_args = {}
- for attr in [
- ATTR_TAGNAME,
- ATTR_DEFAULT_TIMEZONE,
- ATTR_TRACE,
- ATTR_ENABLE_SSM_MAINTENANCE_WINDOWS,
- ATTR_SCHEDULE_CLUSTERS,
- ATTR_CREATE_RDS_SNAPSHOT,
- ATTR_USE_METRICS,
- ATTR_SCHEDULE_LAMBDA_ACCOUNT,
- ATTR_SCHEDULER_ROLE_NAME,
- ATTR_ORGANIZATION_ID,
- ATTR_AWS_PARTITION,
- ATTR_NAMESPACE,
- ATTR_STARTED_TAGS,
- ATTR_STOPPED_TAGS,
- ]:
- config_args[attr] = d.get(attr, None)
-
- for attr in [ATTR_REGIONS, ATTR_REMOTE_ACCOUNT_IDS, ATTR_SCHEDULED_SERVICES]:
- config_args[attr] = set(d.get(attr, []))
-
- periods = {}
-
- for period_name in d.get(ATTR_PERIODS, {}):
- period_data = d[ATTR_PERIODS][period_name]
- period_args = {ATTR_NAME: period_name}
-
- for attr in [ATTR_BEGINTIME, ATTR_ENDTIME]:
- if attr in period_data:
- period_args[attr] = SchedulerConfigBuilder.get_time_from_string(
- period_data[attr]
- )
-
- for attr in [ATTR_WEEKDAYS, ATTR_MONTHDAYS, ATTR_MONTHS]:
- if attr in period_data:
- period_args[attr] = set(period_data.get(attr, None))
-
- period = RunningPeriod(**period_args)
- periods[period_name] = period
-
- config_args[ATTR_SCHEDULES] = {}
-
- for schedule_name in d.get(ATTR_SCHEDULES, {}):
- schedule_args = {}
- schedule_data = d[ATTR_SCHEDULES][schedule_name]
- for attr in [
- ATTR_NAME,
- ATTR_TIMEZONE,
- ATTR_OVERRIDE_STATUS,
- ATTR_STOP_NEW_INSTANCES,
- ATTR_USE_METRICS,
- ATTR_ENFORCED,
- ATTR_HIBERNATE,
- ATTR_RETAIN_RUNNING,
- ATTR_SSM_MAINTENANCE_WINDOW,
- ATTR_USE_MAINTENANCE_WINDOW,
- ]:
- schedule_args[attr] = schedule_data.get(attr, None)
-
- for attr in [ATTR_SCHEDULE_DT]:
- if attr in schedule_data:
- schedule_args[attr] = dateutil.parser.parse(schedule_data[attr])
-
- if schedule_args[ATTR_OVERRIDE_STATUS] is None:
- schedule_args[ATTR_PERIODS] = []
-
- for period in schedule_data.get(ATTR_PERIODS):
- temp = period.split(configuration.INSTANCE_TYPE_SEP)
- if len(temp) > 1:
- name = temp[0]
- instance_type = temp[1]
- else:
- name = period
- instance_type = None
- schedule_args[ATTR_PERIODS].append(
- {ATTR_PERIOD: periods[name], ATTR_INSTANCE_TYPE: instance_type}
- )
-
- schedule = InstanceSchedule(**schedule_args)
- config_args[ATTR_SCHEDULES][schedule_name] = schedule
-
- config = SchedulerConfig(**config_args)
-
- return config
-
- # noinspection PyTypeChecker
- @staticmethod
- def configuration_as_dict(config):
- """
- This method build a dictionary from a configuration instance to be passed safely in the event of a lambda function
- :param config:
- :return:
- """
- result = {}
-
- for attr in [
- ATTR_TAGNAME,
- ATTR_DEFAULT_TIMEZONE,
- ATTR_TRACE,
- ATTR_NAMESPACE,
- ATTR_SCHEDULER_ROLE_NAME,
- ATTR_ORGANIZATION_ID,
- ATTR_AWS_PARTITION,
- ATTR_ENABLE_SSM_MAINTENANCE_WINDOWS,
- ATTR_USE_METRICS,
- ATTR_SCHEDULE_CLUSTERS,
- ATTR_CREATE_RDS_SNAPSHOT,
- ATTR_SCHEDULE_LAMBDA_ACCOUNT,
- ATTR_STARTED_TAGS,
- ATTR_STOPPED_TAGS,
- ]:
- if attr in config.__dict__ and config.__dict__[attr] is not None:
- result[attr] = config.__dict__[attr]
-
- for attr in [ATTR_STARTED_TAGS, ATTR_STOPPED_TAGS]:
- if attr in config.__dict__ and config.__dict__[attr] is not None:
- result[attr] = ",".join(
- [
- "{}={}".format(t["Key"], t["Value"])
- for t in config.__dict__[attr]
- ]
- )
-
- for attr in [ATTR_REGIONS, ATTR_REMOTE_ACCOUNT_IDS, ATTR_SCHEDULED_SERVICES]:
- if len(config.__dict__[attr]) > 0:
- result[attr] = list(config.__dict__[attr])
-
- result[ATTR_SCHEDULES] = {}
- result[ATTR_PERIODS] = {}
-
- for schedule_name in config.schedules:
- result[ATTR_SCHEDULES][schedule_name] = {}
- schedule = config.schedules[schedule_name]
- for attr in [
- ATTR_NAME,
- ATTR_TIMEZONE,
- ATTR_OVERRIDE_STATUS,
- ATTR_STOP_NEW_INSTANCES,
- ATTR_USE_METRICS,
- ATTR_ENFORCED,
- ATTR_HIBERNATE,
- ATTR_USE_MAINTENANCE_WINDOW,
- ATTR_SSM_MAINTENANCE_WINDOW,
- ATTR_RETAIN_RUNNING,
- ]:
- if attr in schedule.__dict__ and schedule.__dict__[attr] is not None:
- result[ATTR_SCHEDULES][schedule_name][attr] = schedule.__dict__[
- attr
- ]
-
- for attr in [ATTR_SCHEDULE_DT]:
- dt = schedule.__dict__[attr]
- if dt is not None:
- result[ATTR_SCHEDULES][schedule.name][attr] = dt.isoformat()
-
- if schedule.override_status is not None:
- continue
-
- result[ATTR_SCHEDULES][schedule_name][ATTR_PERIODS] = []
-
- for p in schedule.periods:
- period = p[ATTR_PERIOD]
- instance_type = p[ATTR_INSTANCE_TYPE]
- result[ATTR_SCHEDULES][schedule_name][ATTR_PERIODS].append(
- period.name
- + (
- ("{}{}".format(configuration.INSTANCE_TYPE_SEP, instance_type))
- if instance_type
- else ""
- )
- )
- if period.name in result[ATTR_PERIODS]:
- continue
-
- result[ATTR_PERIODS][period.name] = {}
- for attr in [ATTR_BEGINTIME, ATTR_ENDTIME]:
- tm = period.__dict__[attr]
- if tm is not None:
- result[ATTR_PERIODS][period.name][
- attr
- ] = "{:0>2d}:{:0>2d}".format(tm.hour, tm.minute)
-
- for attr in [ATTR_WEEKDAYS, ATTR_MONTHDAYS, ATTR_MONTHS]:
- s = period.__dict__[attr]
- if s is None:
- continue
- result[ATTR_PERIODS][period.name][attr] = list(s)
- return result
-
- @staticmethod
- def is_valid_timezone(tz):
+ def is_valid_timezone(tz: str) -> bool:
"""
Generic and optimized method to test the validity of a timezone name
:param tz:
@@ -597,25 +370,25 @@ def is_valid_timezone(tz):
return SchedulerConfigBuilder.validated_timezone(tz) is not None
@staticmethod
- def validated_timezone(tz):
+ def validated_timezone(tz: str) -> Optional[str]:
"""
Generic and optimized method to get a timezone from a timezone name
:param tz: name of the timezone
:return: timezone instance, None if it not valid
"""
tz_lower = str(tz).lower()
+ # -----------cache----------------#
if tz_lower in SchedulerConfigBuilder._checked_timezones:
return str(SchedulerConfigBuilder._checked_timezones[tz_lower])
if tz_lower in SchedulerConfigBuilder._invalid_timezones:
return None
+ # -----------check----------------#
validated = SchedulerConfigBuilder._all_timezones.get(tz_lower, None)
if validated is not None:
# keep list off approved timezones to make next checks much faster
- SchedulerConfigBuilder._checked_timezones[tz_lower] = pytz.timezone(
- validated
- )
+ SchedulerConfigBuilder._checked_timezones[tz_lower] = ZoneInfo(validated)
return validated
else:
SchedulerConfigBuilder._invalid_timezones.add(tz_lower)
@@ -631,11 +404,11 @@ def _get_timezone(tz_name):
# avoid repeated lookup for invalid timezones
if tz_lower not in SchedulerConfigBuilder._invalid_timezones:
- # case insensitive lookup for format pytz name
+ # case insensitive lookup for timezone name
tz_str = SchedulerConfigBuilder._all_timezones.get(tz_lower)
if tz_str is not None:
# found it, no need to check for invalid timezone here because of lookup
- tz = pytz.timezone(tz_str)
+ tz = ZoneInfo(tz_str)
SchedulerConfigBuilder._checked_timezones[tz_lower] = tz
return tz
diff --git a/source/app/instance_scheduler/configuration/scheduling_context.py b/source/app/instance_scheduler/configuration/scheduling_context.py
new file mode 100644
index 00000000..a30556fe
--- /dev/null
+++ b/source/app/instance_scheduler/configuration/scheduling_context.py
@@ -0,0 +1,305 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import copy
+import datetime
+import time
+from dataclasses import dataclass, field
+from typing import Any, Optional, TypedDict
+from zoneinfo import ZoneInfo
+
+from instance_scheduler import configuration
+from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler.configuration.running_period import RunningPeriod
+from instance_scheduler.util.app_env import get_app_env
+
+
+class TagTemplate(TypedDict):
+ Key: str
+ Value: str
+
+
+@dataclass(frozen=True)
+class SchedulingContext:
+ account_id: str
+ service: str
+ region: str
+ current_dt: datetime.datetime
+ tag_name: str
+ default_timezone: ZoneInfo
+ schedules: dict[str, InstanceSchedule]
+ schedule_clusters: bool
+ trace: bool
+ enable_ssm_maintenance_windows: bool
+ use_metrics: bool
+ namespace: str
+ aws_partition: str
+ scheduler_role_name: str
+ organization_id: str
+ schedule_lambda_account: bool
+ create_rds_snapshot: bool
+ started_tags: list[TagTemplate] = field(default_factory=list)
+ stopped_tags: list[TagTemplate] = field(default_factory=list)
+
+ def get_schedule(self, name: Optional[str]) -> Optional[InstanceSchedule]:
+ """
+ Get a schedule by its name
+ :param name: name of the schedule
+ :return: Schedule, None f it does not exist
+ """
+ return self.schedules[name] if name in self.schedules else None
+
+ def to_dict(self) -> dict[Any, Any]:
+ """
+ build a dictionary from a context instance to be passed safely in the event of a lambda function
+
+ note - adapted from original code, much refactoring is almost certainly possible
+ :param config: input SchedulerConfig
+ :return: the schedule as a dict
+ """
+ result = {}
+
+ # include values only if set?
+ for attr in [
+ "tag_name",
+ "trace",
+ "namespace",
+ "scheduler_role_name",
+ "organization_id",
+ "aws_partition",
+ "enable_ssm_maintenance_windows",
+ "use_metrics",
+ "schedule_clusters",
+ "create_rds_snapshot",
+ "schedule_lambda_account",
+ "started_tags",
+ "stopped_tags",
+ ]:
+ if attr in self.__dict__ and self.__dict__[attr] is not None:
+ result[attr] = self.__dict__[attr]
+
+ result["default_timezone"] = str(self.default_timezone)
+ result["current_dt"] = self.current_dt.isoformat()
+
+ for attr in ["started_tags", "stopped_tags"]:
+ if attr in self.__dict__ and self.__dict__[attr] is not None:
+ result[attr] = ",".join(
+ [
+ "{}={}".format(t.get("Key"), t.get("Value"))
+ for t in self.__dict__[attr]
+ ]
+ )
+
+ for attr in ["region", "account_id", "service"]:
+ result[attr] = self.__dict__[attr]
+
+ # initialize schedules/periods
+ result["schedules"] = {}
+ result["periods"] = {}
+
+ # putting schedule object into list of schedules by key
+ # this could be done recursively
+ for schedule_name in self.schedules:
+ result["schedules"][schedule_name] = {}
+ schedule = self.schedules[schedule_name]
+ for attr in [
+ "name",
+ "timezone",
+ "override_status",
+ "stop_new_instances",
+ "use_metrics",
+ "enforced",
+ "hibernate",
+ "use_maintenance_window",
+ "ssm_maintenance_window",
+ "retain_running",
+ ]:
+ if attr in schedule.__dict__ and schedule.__dict__[attr] is not None:
+ result["schedules"][schedule_name][attr] = schedule.__dict__[attr]
+
+ if schedule.override_status is not None:
+ continue
+
+ result["schedules"][schedule_name]["periods"] = []
+
+ for p in schedule.periods:
+ period = p["period"]
+ instance_type = p.get("instancetype", None)
+ result["schedules"][schedule_name]["periods"].append(
+ period.name
+ + (
+ ("{}{}".format(configuration.INSTANCE_TYPE_SEP, instance_type))
+ if instance_type
+ else ""
+ )
+ )
+ if period.name in result["periods"]:
+ continue
+
+ result["periods"][period.name] = {}
+ for attr in ["begintime", "endtime"]:
+ tm = period.__dict__[attr]
+ if tm is not None:
+ result["periods"][period.name][attr] = "{:0>2d}:{:0>2d}".format(
+ tm.hour, tm.minute
+ )
+
+ for attr in ["weekdays", "monthdays", "months"]:
+ s = period.__dict__[attr]
+ if s is None:
+ continue
+ result["periods"][period.name][attr] = list(s)
+ return result
+
+
+def from_dict(config_dict: dict[Any, Any]) -> SchedulingContext:
+ """
+ build a configuration object instance that is passed as a dictionary in the event of a lambda function
+ :param config_dict: a dictionary representation of a schedule
+ :return: a SchedulerConfig built from the dict
+ """
+
+ config_args = {}
+ for attr in [
+ "tag_name",
+ "trace",
+ "namespace",
+ "scheduler_role_name",
+ "organization_id",
+ "aws_partition",
+ "enable_ssm_maintenance_windows",
+ "use_metrics",
+ "schedule_clusters",
+ "create_rds_snapshot",
+ "schedule_lambda_account",
+ ]:
+ config_args[attr] = config_dict.get(attr, None)
+
+ for attr in ["region", "account_id", "service"]:
+ config_args[attr] = config_dict.get(attr, "")
+
+ config_args["current_dt"] = datetime.datetime.fromisoformat(
+ config_dict.get("current_dt", "")
+ )
+ config_args["default_timezone"] = ZoneInfo(config_dict["default_timezone"])
+
+ for attr in ["started_tags", "stopped_tags"]:
+ config_args[attr] = build_tags_from_template(config_dict.get(attr, ""))
+ periods = {}
+
+ for period_name in config_dict.get("periods", {}):
+ period_data = config_dict["periods"][period_name]
+ period_args = {"name": period_name}
+
+ for attr in ["begintime", "endtime"]:
+ if attr in period_data:
+ period_args[attr] = get_time_from_string(period_data[attr])
+
+ for attr in ["weekdays", "monthdays", "months"]:
+ if attr in period_data:
+ period_args[attr] = set(period_data.get(attr, None))
+
+ period = RunningPeriod(**period_args)
+ periods[period_name] = period
+
+ config_args["schedules"] = {}
+
+ for schedule_name in config_dict.get("schedules", {}):
+ schedule_args = {}
+ schedule_data = config_dict["schedules"][schedule_name]
+ for attr in [
+ "name",
+ "timezone",
+ "override_status",
+ "stop_new_instances",
+ "use_metrics",
+ "enforced",
+ "hibernate",
+ "use_maintenance_window",
+ "ssm_maintenance_window",
+ "retain_running",
+ ]:
+ schedule_args[attr] = schedule_data.get(attr, None)
+
+ if schedule_args["override_status"] is None:
+ schedule_args["periods"] = []
+
+ for schedule_period in schedule_data.get("periods"):
+ temp = schedule_period.split(configuration.INSTANCE_TYPE_SEP)
+ if len(temp) > 1:
+ name = temp[0]
+ instance_type = temp[1]
+ else:
+ name = schedule_period
+ instance_type = None
+ schedule_args["periods"].append(
+ {"period": periods[name], "instancetype": instance_type}
+ )
+
+ schedule = InstanceSchedule(**schedule_args)
+ config_args["schedules"][schedule_name] = schedule
+
+ config = SchedulingContext(**config_args)
+
+ if (
+ config.current_dt.tzinfo is None
+ or config.current_dt.tzinfo.utcoffset(config.current_dt) is None
+ ):
+ raise ValueError(
+ "Attempted to build scheduling_context with timezone unaware scheduling time! time received: "
+ "{}".format(config_dict.get("current_dt"))
+ )
+ # https://docs.python.org/3/library/datetime.html#determining-if-an-object-is-aware-or-naive
+
+ return config
+
+
+def get_time_from_string(timestr: Optional[str]) -> Optional[datetime.time]:
+ """
+ Standardised method to build time object instance from time string
+ :param timestr: string in format as defined in configuration.TIME_FORMAT_STRING
+ :return: time object from time string, None if the time is invalid
+ """
+ if not timestr:
+ return None
+ try:
+ tm = time.strptime(timestr, configuration.TIME_FORMAT_STRING)
+ except ValueError:
+ return None
+ return datetime.time(tm.tm_hour, tm.tm_min, 0)
+
+
+def build_tags_from_template(
+ tags_str: Any, tag_variables: Optional[Any] = None
+) -> list[TagTemplate]:
+ lastkey = None
+ tags = {}
+ for tag in tags_str.split(","):
+ if "=" in tag:
+ t = tag.partition("=")
+ tags[t[0]] = t[2]
+ lastkey = t[0]
+ elif lastkey is not None:
+ tags[lastkey] = ",".join([tags[lastkey], tag])
+
+ tag_vars = {} if tag_variables is None else copy.copy(tag_variables)
+
+ dt = datetime.datetime.now(datetime.timezone.utc)
+ tag_vars.update(
+ {
+ configuration.TAG_VAL_SCHEDULER: get_app_env().stack_name,
+ configuration.TAG_VAL_YEAR: "{:0>4d}".format(dt.year),
+ configuration.TAG_VAL_MONTH: "{:0>2d}".format(dt.month),
+ configuration.TAG_VAL_DAY: "{:0>2d}".format(dt.day),
+ configuration.TAG_VAL_HOUR: "{:0>2d}".format(dt.hour),
+ configuration.TAG_VAL_MINUTE: "{:0>2d}".format(dt.minute),
+ configuration.TAG_VAL_TIMEZONE: "UTC",
+ }
+ )
+
+ for tag in tags:
+ value = tags[tag]
+ if value not in ["", None]:
+ for v in tag_vars:
+ tags[tag] = tags[tag].replace("{{{}}}".format(v), tag_vars[v])
+
+ return [{"Key": t, "Value": tags[t]} for t in tags]
diff --git a/source/app/instance_scheduler/configuration/setbuilders/month_setbuilder.py b/source/app/instance_scheduler/configuration/setbuilders/month_setbuilder.py
index 4e5cc003..014e6e4e 100644
--- a/source/app/instance_scheduler/configuration/setbuilders/month_setbuilder.py
+++ b/source/app/instance_scheduler/configuration/setbuilders/month_setbuilder.py
@@ -12,7 +12,7 @@ class MonthSetBuilder(SetBuilder):
Class for building month sets, 1-12 ans jan-dec
"""
- def __init__(self, wrap=True, ignorecase=True):
+ def __init__(self, wrap: bool = True, ignorecase: bool = True) -> None:
"""
Initializes set builder for month sets
:param wrap: Set to True to allow wrapping at last month of the year
diff --git a/source/app/instance_scheduler/configuration/setbuilders/monthday_setbuilder.py b/source/app/instance_scheduler/configuration/setbuilders/monthday_setbuilder.py
index 11501b50..3711cd67 100644
--- a/source/app/instance_scheduler/configuration/setbuilders/monthday_setbuilder.py
+++ b/source/app/instance_scheduler/configuration/setbuilders/monthday_setbuilder.py
@@ -1,8 +1,7 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-
import calendar
+from typing import Optional
from instance_scheduler.configuration.setbuilders.setbuilder import SetBuilder
@@ -15,7 +14,7 @@ class MonthdaySetBuilder(SetBuilder):
WILDCARD_WEEKDAY = "W"
WILDCARD_LAST_WEEKDAY = "L"
- def __init__(self, year, month):
+ def __init__(self, year: int, month: int) -> None:
"""
Initializes monthday set builder.
:param year: Year of month to build sets for, only required for month aware 'W' and 'L' features in expressions
@@ -37,18 +36,18 @@ def __init__(self, year, month):
self._post_custom_parsers = [self._parse_weekday]
- def _parse_weekday(self, day_str):
+ def _parse_weekday(self, day_str: str) -> Optional[list[int]]:
# dayW return working day nearest to day
return self._get_weekday(day_str)
- def _parse_unknown(self, item):
+ def _parse_unknown(self, item: str) -> Optional[list[int]]:
return [] if item in [str(d) for d in range(self.last, 32)] else None
- def _seperator_characters(self):
+ def _seperator_characters(self) -> str:
# adding W to separator characters, it should not be formatted
return SetBuilder._seperator_characters(self) + self.WILDCARD_WEEKDAY
- def _get_weekday(self, day_str):
+ def _get_weekday(self, day_str: str) -> Optional[list[int]]:
# returns working day nearest to day in month, string is in format dayW
if (1 < len(day_str) <= 3) and day_str.endswith(self.WILDCARD_WEEKDAY):
day = self._get_value_by_str(day_str[0:-1])
diff --git a/source/app/instance_scheduler/configuration/setbuilders/setbuilder.py b/source/app/instance_scheduler/configuration/setbuilders/setbuilder.py
index a5dff61b..66cb43c1 100644
--- a/source/app/instance_scheduler/configuration/setbuilders/setbuilder.py
+++ b/source/app/instance_scheduler/configuration/setbuilders/setbuilder.py
@@ -1,8 +1,10 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-
import logging
+from collections.abc import Callable, Sequence
+from typing import Optional
+
+Parser = Callable[[str], Optional[list[int]]]
class SetBuilder:
@@ -27,17 +29,17 @@ class SetBuilder:
def __init__(
self,
- names=None,
- min_value=None,
- max_value=None,
- offset=None,
- wrap=False,
- ignorecase=True,
- significant_name_characters=None,
- first_item_wildcard=WILDCARD_FIRST,
- all_items_wildcards=WILDCARD_ALL,
- last_item_wildcard=WILDCARD_LAST,
- ):
+ names: Optional[Sequence[str]] = None,
+ min_value: Optional[int] = None,
+ max_value: Optional[int] = None,
+ offset: Optional[int] = None,
+ wrap: bool = False,
+ ignorecase: bool = True,
+ significant_name_characters: Optional[int] = None,
+ first_item_wildcard: str = WILDCARD_FIRST,
+ all_items_wildcards: str = WILDCARD_ALL,
+ last_item_wildcard: str = WILDCARD_LAST,
+ ) -> None:
"""
:param names: Names for values
@@ -123,11 +125,11 @@ def __init__(
)
# custom parsers to be executed before standard parsers
- self._pre_custom_parsers = []
+ self._pre_custom_parsers: list[Parser] = []
# custom parsers to be executes after standard parsers
- self._post_custom_parsers = []
+ self._post_custom_parsers: list[Parser] = []
# setup list of standard parsers
- self._standard_parsers = [
+ self._standard_parsers: list[Parser] = [
self._parse_name, # name
self._parse_value, # value, first and last wildcard
self._parse_name_range, # name-name
@@ -139,7 +141,7 @@ def __init__(
self._parse_value_range_incr,
] # value-value/incr
- def build(self, set_spec):
+ def build(self, set_spec: str | list[str] | set[str]) -> set[int]:
"""
Builds set of values from string or list of strings
:param set_spec: Sets as comma separated string or list of strings
@@ -153,42 +155,8 @@ def build(self, set_spec):
else:
raise ValueError("set_str argument must be of type string, set or array")
- def str(self, the_set):
- """
- Displays set as a string using ',' to separate values and '-' for sequent ranges
- :param the_set: Set to display
- :return: String to display the set in a normalized format
- """
- result = []
-
- # gets list of single and subsequent items in the set
- def get_sub_sets():
- if the_set is not None and len(the_set) > 0:
- temp = sorted(the_set)
- last = temp[0]
- current = {temp[0]}
-
- for index in range(1, len(temp)):
- if temp[index] == last + 1:
- current.add(temp[index])
- else:
- yield current
- current = {temp[index]}
- last = temp[index]
-
- yield current
-
- # build string from subset
- for subset in get_sub_sets():
- s = self._displaynames[min(subset) - self._offset]
- if len(subset) > 1:
- s = "-".join([s, self._displaynames[max(subset) - self._offset]])
- result.append(s)
-
- return ", ".join(result)
-
@property
- def first(self):
+ def first(self) -> int:
"""
Return lowest possible value in set
:return: Lowest possible value in set
@@ -196,7 +164,7 @@ def first(self):
return self._offset
@property
- def last(self):
+ def last(self) -> int:
"""
Return highest possible value in set
:return: Highest possible value in set
@@ -204,7 +172,7 @@ def last(self):
return len(self._names) - 1 + self._offset
@property
- def all(self):
+ def all(self) -> set[int]:
"""
Returns all items in set
:return: All items in set
@@ -212,56 +180,57 @@ def all(self):
return set(self._all)
@property
- def _all(self):
+ def _all(self) -> list[int]:
# internal function to return all items in set
return [val + self._offset for val in range(0, len(self._values))]
- def _parse_name(self, name_str):
+ def _parse_name(self, name_str: str) -> Optional[list[int]]:
# gets a set item by its name
return self._get_single_item(name_str, self._get_value_by_name)
- def _parse_value(self, value_str):
+ def _parse_value(self, value_str: str) -> Optional[list[int]]:
# value
return self._get_single_item(value_str, self._get_value_by_str)
- def _parse_name_range(self, name_range_str):
+ def _parse_name_range(self, name_range_str: str) -> Optional[list[int]]:
# name-name
return self._get_range_from_str(name_range_str, self._get_value_by_name)
- def _parse_value_range(self, value_range_str):
+ def _parse_value_range(self, value_range_str: str) -> Optional[list[int]]:
# value-value
return self._get_range_from_str(value_range_str, fn=self._get_value_by_str)
- def _parse_name_incr(self, name_incr_str):
+ def _parse_name_incr(self, name_incr_str: str) -> Optional[list[int]]:
# name/incr
return self._get_increment(name_incr_str, self._get_name_incr)
- def _parse_value_incr(self, value_incr_str):
+ def _parse_value_incr(self, value_incr_str: str) -> Optional[list[int]]:
# value/incr
return self._get_increment(value_incr_str, self._get_value_incr)
- def _parse_name_range_incr(self, name_range_incr_str):
+ def _parse_name_range_incr(self, name_range_incr_str: str) -> Optional[list[int]]:
# name-name/incr
return self._get_increment(name_range_incr_str, fn=self._get_name_range_incr)
- def _parse_value_range_incr(self, value_range_incr_str):
+ def _parse_value_range_incr(self, value_range_incr_str: str) -> Optional[list[int]]:
# value-value/incr
return self._get_increment(value_range_incr_str, fn=self._get_value_range_incr)
- def _parse_all(self, all_wildcard_str):
+ def _parse_all(self, all_wildcard_str: str) -> Optional[list[int]]:
# wildcards
if (
len(all_wildcard_str) == 1
and all_wildcard_str in self._all_items_wildcard_characters
):
return self._all
+ return None
- def _parse_unknown(self, _):
+ def _parse_unknown(self, _: str) -> Optional[list[int]]:
# handle unknown items
return None
@property
- def _parsers(self):
+ def _parsers(self) -> list[Parser]:
# flattened list of all parsers
return [
parser
@@ -273,7 +242,7 @@ def _parsers(self):
for parser in parsers
]
- def _special_items(self):
+ def _special_items(self) -> str:
# special items that do not need pre-formatting or must be excluded from formatting
return "".join(
[
@@ -283,11 +252,11 @@ def _special_items(self):
]
)
- def _seperator_characters(self):
+ def _seperator_characters(self) -> str:
# character that separates name from instructions like increments
return SetBuilder.INCREMENT_CHARACTER
- def _get_set_items(self, set_string_list):
+ def _get_set_items(self, set_string_list: list[str]) -> set[int]:
# gets the items from a list of strings
set_items = set()
@@ -322,7 +291,6 @@ def _get_set_items(self, set_string_list):
self._parse_unknown.__name__, set_str, value
)
)
- # noinspection PyTypeChecker
set_items.update(set(value))
else:
# if it does not return a value then raise an exception because of an unknown item
@@ -330,7 +298,7 @@ def _get_set_items(self, set_string_list):
return set_items
- def _format_item(self, set_str):
+ def _format_item(self, set_str: str) -> str:
# pre-processes the item before trying to parse it
s = set_str.strip()
@@ -368,17 +336,19 @@ def _format_item(self, set_str):
return s
@staticmethod
- def _get_single_item(item_str, fn):
+ def _get_single_item(
+ item_str: str, fn: Callable[[str], Optional[int]]
+ ) -> Optional[list[int]]:
# function to return single set items in a uniform way as a set
value = fn(item_str)
if value is not None:
return [value]
return None
- def _get_value_by_name(self, name_str):
+ def _get_value_by_name(self, name_str: str) -> Optional[int]:
# gets the value of a set item by its name, also handled first and last item wildcards
# internal iterator for testing for names
- def from_name(name):
+ def from_name(name: str) -> Optional[int]:
if name in self._names:
return self._names.index(name) + self._offset
return None
@@ -390,7 +360,7 @@ def from_name(name):
return value
return None
- def _get_value_by_str(self, value_str):
+ def _get_value_by_str(self, value_str: str) -> Optional[int]:
# gets the value of a set item by its numeric string
s = value_str
while len(s) > 1 and s[0] == "0":
@@ -399,7 +369,9 @@ def _get_value_by_str(self, value_str):
return self._values.index(s) + self._offset
return None
- def _get_range_from_str(self, range_str, fn, incr=1):
+ def _get_range_from_str(
+ self, range_str: str, fn: Callable[[str], Optional[int]], incr: int = 1
+ ) -> Optional[list[int]]:
# gets a range from a string, items are retrieved using the function specified by fn
# check if there is a range separator in the string
set_range = range_str.split(self.RANGE_CHARACTER)
@@ -413,7 +385,7 @@ def _get_range_from_str(self, range_str, fn, incr=1):
return self._get_range(start, end, incr)
return None
- def _get_last_value(self, last_wildcard_str):
+ def _get_last_value(self, last_wildcard_str: str) -> Optional[int]:
# returns the last possible value if the str is the last wildcard character
if (
len(last_wildcard_str) == 1
@@ -422,7 +394,7 @@ def _get_last_value(self, last_wildcard_str):
return self.last
return None
- def _get_first_value(self, first_wildcard_str):
+ def _get_first_value(self, first_wildcard_str: str) -> Optional[int]:
# returns the first possible value if the str is the first item wildcard character
if (
len(first_wildcard_str) == 1
@@ -431,7 +403,7 @@ def _get_first_value(self, first_wildcard_str):
return self.first
return None
- def _get_range(self, start, end, step=1):
+ def _get_range(self, start: int, end: int, step: int = 1) -> list[int]:
# gets a range of items for the specified start, end and step value
# check if wrapping is needed and allowed
@@ -462,7 +434,9 @@ def _get_range(self, start, end, step=1):
return result
@staticmethod
- def _get_increment(incr_str, fn):
+ def _get_increment(
+ incr_str: str, fn: Callable[[str, int], Optional[list[int]]]
+ ) -> Optional[list[int]]:
# returns a set of values using a start value and a increment
temp = incr_str.split(SetBuilder.INCREMENT_CHARACTER)
# check if there is an increment character and if the increment value is present and valid
@@ -480,7 +454,9 @@ def _get_increment(incr_str, fn):
return fn(temp[0], incr)
return None
- def _get_increment_by_string(self, incr_string, fn, incr):
+ def _get_increment_by_string(
+ self, incr_string: str, fn: Callable[[str], Optional[int]], incr: int
+ ) -> Optional[list[int]]:
# get increment items for start value retrieved by function fn
start = fn(incr_string)
@@ -488,32 +464,38 @@ def _get_increment_by_string(self, incr_string, fn, incr):
return self._get_range(start=start, end=self.last, step=incr)
return None
- def _get_name_incr(self, name_incr_str, incr):
+ def _get_name_incr(self, name_incr_str: str, incr: int) -> Optional[list[int]]:
# get increment items for start value retrieved by its name
return self._get_increment_by_string(
name_incr_str, self._get_value_by_name, incr
)
- def _get_value_incr(self, value_incr_str, incr):
+ def _get_value_incr(self, value_incr_str: str, incr: int) -> Optional[list[int]]:
# get increment items for start value retrieved by its value string
return self._get_increment_by_string(
value_incr_str, self._get_value_by_str, incr
)
- def _get_range_increment(self, incr_str, fn, incr):
+ def _get_range_increment(
+ self, incr_str: str, fn: Callable[[str], Optional[int]], incr: int
+ ) -> Optional[list[int]]:
# gets increment values from a range specified by the name of the start and end value retrieved by function fn
set_range = self._get_range_from_str(incr_str, fn, incr)
if set_range is not None:
return set_range
return None
- def _get_name_range_incr(self, name_range_incr_str, incr):
+ def _get_name_range_incr(
+ self, name_range_incr_str: str, incr: int
+ ) -> Optional[list[int]]:
# gets increment values from a range specified by the name of the start and end value retrieved by their names
return self._get_range_increment(
name_range_incr_str, self._get_value_by_name, incr
)
- def _get_value_range_incr(self, value_range_incr_str, incr):
+ def _get_value_range_incr(
+ self, value_range_incr_str: str, incr: int
+ ) -> Optional[list[int]]:
# gets increment values from a range specified by the name of the start and end value retrieved by their value strings
return self._get_range_increment(
value_range_incr_str, self._get_value_by_str, incr
diff --git a/source/app/instance_scheduler/configuration/setbuilders/weekday_setbuilder.py b/source/app/instance_scheduler/configuration/setbuilders/weekday_setbuilder.py
index c6172bfb..acf0adcc 100644
--- a/source/app/instance_scheduler/configuration/setbuilders/weekday_setbuilder.py
+++ b/source/app/instance_scheduler/configuration/setbuilders/weekday_setbuilder.py
@@ -1,12 +1,36 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-
import calendar
+from collections.abc import Callable
+from typing import Optional
from instance_scheduler.configuration.setbuilders.setbuilder import SetBuilder
+def _requires_date_attributes(
+ fn: Callable[["WeekdaySetBuilder", str], Optional[list[int]]]
+) -> Callable[["WeekdaySetBuilder", str], Optional[list[int]]]:
+ # this modifier is used to mark to use methods that need year, day and month which are optional for the builder
+ def check(self: "WeekdaySetBuilder", value: str) -> Optional[list[int]]:
+ if self._year is None or self._month is None or self._day is None:
+ raise ValueError(
+ "year, month and day parameters must be specified when creating the {} for using method {}".format(
+ self.__class__.__name__, fn.__name__
+ )
+ )
+
+ # and if we're checking for the first time then get the first weekday and numbers for the month
+ if self._first_weekday_in_month is None:
+ self._first_weekday_in_month, self._days_in_month = calendar.monthrange(
+ self._year, self._month
+ )
+
+ return fn(self, value)
+
+ check.__name__ = fn.__name__
+ return check
+
+
class WeekdaySetBuilder(SetBuilder):
"""
Class to build sets for weekdays, 0-6 or Mon-Sun, day#n for nth occurrence of day in month, or L for last
@@ -16,7 +40,14 @@ class WeekdaySetBuilder(SetBuilder):
WEEKDAY_NUMBER_CHAR = "#"
LAST_DAY_WILDCARD = "L"
- def __init__(self, wrap=True, year=None, month=None, day=None, ignorecase=True):
+ def __init__(
+ self,
+ wrap: bool = True,
+ year: Optional[int] = None,
+ month: Optional[int] = None,
+ day: Optional[int] = None,
+ ignorecase: bool = True,
+ ) -> None:
"""
:param wrap: Set to True to allow wrapping at last day of the week
@@ -36,8 +67,8 @@ def __init__(self, wrap=True, year=None, month=None, day=None, ignorecase=True):
self._year = year
self._month = month
self._day = day
- self._first_weekday_in_month = None
- self._days_in_month = None
+ self._first_weekday_in_month: Optional[int] = None
+ self._days_in_month: Optional[int] = None
self._post_custom_parsers = [
self._parse_name_number, # name#num
@@ -46,7 +77,7 @@ def __init__(self, wrap=True, year=None, month=None, day=None, ignorecase=True):
self._parse_value_last_weekday,
] # valueL
- def _seperator_characters(self):
+ def _seperator_characters(self) -> str:
# Add last day wildcard as it needs for formatting before parsing
return (
SetBuilder._seperator_characters(self)
@@ -54,46 +85,23 @@ def _seperator_characters(self):
+ self.LAST_DAY_WILDCARD
)
- # noinspection PyMethodParameters
- def _requires_date_attributes(fn):
- # this modifier is used to mark to use methods that need year, day and month which are optional for the builder
- def check(self, *args, **kwargs):
- if self._year is None or self._month is None or self._day is None:
- raise ValueError(
- "year, month and day parameters must be specified when creating the {} for using method {}".format(
- self.__class__.__name__, fn.__name__
- )
- )
-
- # and if we're checking for the first time then get the first weekday and numbers for the month
- if self._first_weekday_in_month is None:
- self._first_weekday_in_month, self._days_in_month = calendar.monthrange(
- self._year, self._month
- )
-
- # noinspection PyCallingNonCallable
- return fn(self, *args, **kwargs)
-
- check.__name__ = fn.__name__
- return check
-
- # noinspection PyArgumentList,PyArgumentList
@_requires_date_attributes
- def _parse_name_number(self, name_number_str):
+ def _parse_name_number(self, name_number_str: str) -> Optional[list[int]]:
# weekday_name#occurence
return self._get_occurrence_item(
number_str=name_number_str, fn=self._get_value_by_name
)
- # noinspection PyArgumentList,PyArgumentList
@_requires_date_attributes
- def _parse_value_number(self, value_number_str):
+ def _parse_value_number(self, value_number_str: str) -> Optional[list[int]]:
# weekday value# occurrence
return self._get_occurrence_item(
number_str=value_number_str, fn=self._get_value_by_str
)
- def _get_occurrence_item(self, number_str, fn):
+ def _get_occurrence_item(
+ self, number_str: str, fn: Callable[[str], Optional[int]]
+ ) -> Optional[list[int]]:
# gets the nth occurrence of a weekday retrieved by function fn
# check for separator
@@ -125,31 +133,37 @@ def _get_occurrence_item(self, number_str, fn):
return None
- def _get_day_for_first_occurrence_month(self, weekday):
+ def _get_day_for_first_occurrence_month(self, weekday: int) -> int:
# calculated the first occurrence of a weekday in a month
+ if self._first_weekday_in_month is None:
+ raise ValueError("Expected first weekday in month to be set")
+
day = 1
if weekday != self._first_weekday_in_month:
day += (weekday - self._first_weekday_in_month) % 7
return day
- # noinspection PyArgumentList,PyArgumentList
@_requires_date_attributes
- def _parse_name_last_weekday(self, name_last_weekday):
+ def _parse_name_last_weekday(self, name_last_weekday: str) -> Optional[list[int]]:
# nameL, returns last occurrence of weekday, specified by its name, in a month
return self._get_last_day_for_weekday_in_month(
name_last_weekday, self._get_value_by_name
)
- # noinspection PyArgumentList,PyArgumentList
@_requires_date_attributes
- def _parse_value_last_weekday(self, value_last_weekday):
+ def _parse_value_last_weekday(self, value_last_weekday: str) -> Optional[list[int]]:
# valueL, returns last occurrence of weekday, specified by its value, string in a month
return self._get_last_day_for_weekday_in_month(
value_last_weekday, self._get_value_by_str
)
- def _get_last_day_for_weekday_in_month(self, last_weekday_str, fn):
+ def _get_last_day_for_weekday_in_month(
+ self, last_weekday_str: str, fn: Callable[[str], Optional[int]]
+ ) -> Optional[list[int]]:
# weekdayL, returns last occurrence of weekday, retrieved by function fn, string in a month
+ if self._days_in_month is None:
+ raise ValueError("Expected days in month to be set")
+
if last_weekday_str.endswith(WeekdaySetBuilder.LAST_DAY_WILDCARD):
weekday = fn(last_weekday_str[:-1])
if weekday is not None:
@@ -159,3 +173,4 @@ def _get_last_day_for_weekday_in_month(self, last_weekday_str, fn):
while day_for_number_weekday + 7 <= self._days_in_month:
day_for_number_weekday += 7
return [weekday] if day_for_number_weekday == self._day else []
+ return None
diff --git a/source/app/instance_scheduler/handler/__init__.py b/source/app/instance_scheduler/handler/__init__.py
new file mode 100644
index 00000000..3cc2eb88
--- /dev/null
+++ b/source/app/instance_scheduler/handler/__init__.py
@@ -0,0 +1,28 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from collections.abc import Sequence as _Sequence
+from typing import Any as _Any
+from typing import Final as _Final
+
+from instance_scheduler.handler.base import Handler
+from instance_scheduler.handler.cfn_schedule import CfnScheduleHandler
+from instance_scheduler.handler.cli import CliHandler
+from instance_scheduler.handler.collect_configuration_description import (
+ CollectConfigurationDescription,
+)
+from instance_scheduler.handler.config_resource import SchedulerSetupHandler
+from instance_scheduler.handler.scheduling_orchestrator import (
+ SchedulingOrchestratorHandler,
+)
+from instance_scheduler.handler.scheduling_request import SchedulingRequestHandler
+from instance_scheduler.handler.spoke_registration import SpokeRegistrationHandler
+
+handlers: _Final[_Sequence[type[Handler[_Any]]]] = (
+ SchedulingRequestHandler,
+ SchedulerSetupHandler,
+ CfnScheduleHandler,
+ CliHandler,
+ SchedulingOrchestratorHandler,
+ SpokeRegistrationHandler,
+ CollectConfigurationDescription,
+)
diff --git a/source/app/instance_scheduler/handler/base.py b/source/app/instance_scheduler/handler/base.py
new file mode 100644
index 00000000..49c8d9de
--- /dev/null
+++ b/source/app/instance_scheduler/handler/base.py
@@ -0,0 +1,27 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from abc import ABC, abstractmethod
+from collections.abc import Mapping
+from typing import TYPE_CHECKING, Any, Generic, TypeGuard, TypeVar
+
+if TYPE_CHECKING:
+ from aws_lambda_powertools.utilities.typing import LambdaContext
+else:
+ LambdaContext = object
+
+T = TypeVar("T")
+
+
+class Handler(ABC, Generic[T]):
+ @classmethod
+ @abstractmethod
+ def is_handling_request(cls, event: Mapping[str, Any]) -> TypeGuard[T]:
+ pass
+
+ @abstractmethod
+ def __init__(self, event: T, context: LambdaContext) -> None:
+ pass
+
+ @abstractmethod
+ def handle_request(self) -> Any:
+ pass
diff --git a/source/app/instance_scheduler/requesthandlers/schedule_resource_handler.py b/source/app/instance_scheduler/handler/cfn_schedule.py
similarity index 73%
rename from source/app/instance_scheduler/requesthandlers/schedule_resource_handler.py
rename to source/app/instance_scheduler/handler/cfn_schedule.py
index 9a1fa73f..9a34a19c 100644
--- a/source/app/instance_scheduler/requesthandlers/schedule_resource_handler.py
+++ b/source/app/instance_scheduler/handler/cfn_schedule.py
@@ -1,15 +1,27 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-
-from datetime import datetime
+from collections.abc import Mapping
+from datetime import datetime, timezone
+from typing import TYPE_CHECKING, Any, Optional, TypedDict, TypeGuard
from instance_scheduler import configuration
-from instance_scheduler.configuration.config_admin import ConfigAdmin
+from instance_scheduler.configuration.config_admin import (
+ ConfigAdmin,
+ ConfigTablePeriodItem,
+)
from instance_scheduler.util import safe_json
-from instance_scheduler.util.custom_resource import CustomResource
+from instance_scheduler.util.app_env import get_app_env
+from instance_scheduler.util.custom_resource import (
+ CustomResource,
+ CustomResourceRequest,
+)
from instance_scheduler.util.logger import Logger
+if TYPE_CHECKING:
+ from aws_lambda_powertools.utilities.typing import LambdaContext
+else:
+ LambdaContext = object
+
INF_DELETE_SCHEDULE = "Deleted schedule {}"
INF_DELETED_PERIOD = "Deleted period {}"
INF_PERIOD_CREATED = "Created period {}"
@@ -55,7 +67,6 @@
PROP_RETAIN_RUNNING,
PROP_METRICS,
PROP_NAME,
- PROP_OVERRIDE_STATUS,
PROP_OVERWRITE,
PROP_PERIODS,
PROP_STOP_NEW,
@@ -65,7 +76,10 @@
PROP_NO_STACK_PREFIX,
PROP_HIBERNATE,
"ServiceToken",
+ # these values used to be part of the sample template in the IG, but have been removed 7/23,
+ # customers may still have old templates that include them property, so we need to not break compatibility
"Timeout",
+ PROP_OVERRIDE_STATUS,
]
VALID_PERIOD_PROPERTIES = [
@@ -81,12 +95,41 @@
LOG_STREAM = "{}-{:0>4d}{:0>2d}{:0>2d}"
-class ScheduleResourceHandler(CustomResource):
+class CfnSchedulePeriodProperties(TypedDict, total=False):
+ Description: Optional[str]
+ BeginTime: Optional[str]
+ EndTime: Optional[str]
+ InstanceType: Optional[str]
+ MonthDays: Optional[str]
+ Months: Optional[str]
+ WeekDays: Optional[str]
+
+
+class CfnScheduleResourceProperties(TypedDict, total=False):
+ ServiceToken: str
+ NoStackPrefix: Optional[str]
+ Name: Optional[str]
+ Description: Optional[str]
+ Timezone: Optional[str]
+ Enforced: Optional[str]
+ Hibernate: Optional[str]
+ RetainRunning: Optional[str]
+ StopNewInstances: Optional[str]
+ UseMaintenanceWindow: Optional[str]
+ SsmMaintenanceWindow: Optional[str]
+ Periods: list[CfnSchedulePeriodProperties]
+
+
+class CfnScheduleHandler(CustomResource[CfnScheduleResourceProperties]):
"""
Implements custom resource handler for CFN support for schedules/periods
"""
- def __init__(self, event, context):
+ def __init__(
+ self,
+ event: CustomResourceRequest[CfnScheduleResourceProperties],
+ context: LambdaContext,
+ ) -> None:
"""
Initializes instance
:param event: CFN event
@@ -95,15 +138,23 @@ def __init__(self, event, context):
CustomResource.__init__(self, event, context)
self.number_of_periods = 0
+ app_env = get_app_env()
classname = self.__class__.__name__
- dt = datetime.utcnow()
- logstream = LOG_STREAM.format(classname, dt.year, dt.month, dt.day)
- self._logger = Logger(logstream=logstream, buffersize=20, context=context)
+ dt = datetime.now(timezone.utc)
+ log_stream = LOG_STREAM.format(classname, dt.year, dt.month, dt.day)
+ self._logger = Logger(
+ log_group=app_env.log_group,
+ log_stream=log_stream,
+ topic_arn=app_env.topic_arn,
+ debug=app_env.enable_debug_logging,
+ )
self._admin = ConfigAdmin(logger=self._logger, context=context)
@staticmethod
- def is_handling_request(event):
+ def is_handling_request(
+ event: Mapping[str, Any]
+ ) -> TypeGuard[CustomResourceRequest[CfnScheduleResourceProperties]]:
"""
Tests if this handler handles the event
:param event: Tested event
@@ -115,13 +166,20 @@ def is_handling_request(event):
)
@classmethod
- def _set_if_specified(cls, source, source_name, dest, dest_name=None, default=None):
+ def _set_if_specified(
+ cls,
+ source: Any,
+ source_name: Any,
+ dest: Any,
+ dest_name: Any = None,
+ default: Any = None,
+ ) -> None:
val = source.get(source_name, default)
if val is not None:
dest[dest_name if dest_name is not None else source_name] = val
@property
- def _schedule_resource_name(self):
+ def _schedule_resource_name(self) -> Any:
name = self.resource_properties.get(PROP_NAME, None)
if name is None:
name = self.logical_resource_id
@@ -132,7 +190,7 @@ def _schedule_resource_name(self):
return name
return "{}-{}".format(self.stack_name, name)
- def _create_period(self, period):
+ def _create_period(self, period: Any) -> tuple[str, Any]:
self.number_of_periods += 1
period_name = PERIOD_NAME.format(
@@ -148,7 +206,7 @@ def _create_period(self, period):
)
)
- create_period_args = {configuration.NAME: period_name}
+ create_period_args: ConfigTablePeriodItem = {"name": period_name}
self._set_if_specified(
period, PROP_BEGIN_TIME, create_period_args, configuration.BEGINTIME
@@ -166,22 +224,23 @@ def _create_period(self, period):
period, PROP_WEEKDAYS, create_period_args, configuration.WEEKDAYS
)
- create_period_args[configuration.DESCRIPTION] = PERIOD_DESCRIPTION.format(
+ create_period_args["description"] = PERIOD_DESCRIPTION.format(
self._schedule_resource_name, self.number_of_periods
)
description_config = period.get(PROP_DESCRIPTION, None)
if description_config is not None:
- create_period_args[configuration.DESCRIPTION] = "{}, {}".format(
- description_config, create_period_args[configuration.DESCRIPTION]
+ create_period_args["description"] = "{}, {}".format(
+ description_config, create_period_args["description"]
)
- period = self._admin.create_period(**create_period_args)
+
instance_type = period.get(PROP_INSTANCE_TYPE, None)
+ period = self._admin.create_period(create_period_args)
self._logger.info(INF_PERIOD_CREATED, safe_json(period, 3))
return period_name, instance_type
- def _delete_periods(self):
+ def _delete_periods(self) -> None:
i = 0
while True:
i += 1
@@ -192,7 +251,7 @@ def _delete_periods(self):
else:
self._logger.info(INF_DELETED_PERIOD, name)
- def _create_schedule(self):
+ def _create_schedule(self) -> None:
self._logger.info(INF_SCHEDULE_NAME, self._schedule_resource_name)
create_schedule_args = {configuration.NAME: self._schedule_resource_name}
@@ -282,7 +341,7 @@ def _create_schedule(self):
periods = []
try:
self.number_of_periods = 0
- for period in ps.get(PROP_PERIODS, []):
+ for period in ps.get(PROP_PERIODS, []): # type:ignore[attr-defined]
period_name, instance_type = self._create_period(period)
if instance_type is not None:
period_name = "{}{}{}".format(
@@ -291,7 +350,8 @@ def _create_schedule(self):
periods.append(period_name)
create_schedule_args[configuration.PERIODS] = periods
- schedule = self._admin.create_schedule(**create_schedule_args)
+ schedule = self._admin.create_schedule(create_schedule_args) # type: ignore[arg-type]
+ # todo remove the typing ignore here (requires refactoring this method)
self.physical_resource_id = self._schedule_resource_name
self._logger.info(INF_SCHEDULE_CREATED, safe_json(schedule, 3))
@@ -299,7 +359,7 @@ def _create_schedule(self):
self._delete_periods()
raise ex
- def _delete_schedule(self):
+ def _delete_schedule(self) -> None:
schedule = self._admin.delete_schedule(
name=self._schedule_resource_name, exception_if_not_exists=False
)
@@ -307,38 +367,38 @@ def _delete_schedule(self):
self._delete_periods()
self._logger.info(INF_DELETE_SCHEDULE, self._schedule_resource_name)
- def _update_schedule(self):
+ def _update_schedule(self) -> None:
self._delete_schedule()
self._create_schedule()
- def _create_request(self):
+ def _create_request(self) -> bool:
try:
self._create_schedule()
return True
except Exception as ex:
- self._logger.error(ex)
+ self._logger.error(str(ex))
return False
finally:
self._logger.flush()
- def _update_request(self):
+ def _update_request(self) -> bool:
try:
self._update_schedule()
return True
except Exception as ex:
- self._logger.error(ex)
+ self._logger.error(str(ex))
return False
finally:
self._logger.flush()
# handles Delete request from CloudFormation
- def _delete_request(self):
+ def _delete_request(self) -> bool:
try:
self._delete_schedule()
return True
except Exception as ex:
- self._logger.error(ex)
+ self._logger.error(str(ex))
return False
finally:
self._logger.flush()
diff --git a/source/app/instance_scheduler/requesthandlers/admin_cli_request_handler.py b/source/app/instance_scheduler/handler/cli.py
similarity index 74%
rename from source/app/instance_scheduler/requesthandlers/admin_cli_request_handler.py
rename to source/app/instance_scheduler/handler/cli.py
index 260c4f77..9fa20f54 100644
--- a/source/app/instance_scheduler/requesthandlers/admin_cli_request_handler.py
+++ b/source/app/instance_scheduler/handler/cli.py
@@ -1,28 +1,41 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-
import json
-from datetime import datetime
+from collections.abc import Mapping
+from datetime import datetime, timezone
+from typing import TYPE_CHECKING, Any, TypeGuard
import jmespath
from instance_scheduler import configuration
from instance_scheduler.configuration.config_admin import ConfigAdmin
+from instance_scheduler.handler.base import Handler
+from instance_scheduler.ops_metrics.metric_type.cli_request_metric import (
+ CliRequestMetric,
+)
+from instance_scheduler.ops_metrics.metrics import collect_metric
from instance_scheduler.util import safe_json
+from instance_scheduler.util.app_env import get_app_env
from instance_scheduler.util.logger import Logger
+if TYPE_CHECKING:
+ from aws_lambda_powertools.utilities.typing import LambdaContext
+else:
+ LambdaContext = object
+
CLI_SOURCE = "scheduler.cli"
LOG_STREAM = "{}-{:0>4d}{:0>2d}{:0>2d}"
+AdminCliRequest = dict[str, Any]
+
-class AdminCliRequestHandler(object):
+class CliHandler(Handler[AdminCliRequest]):
"""
Class to handles requests from admin CLI
"""
- def __init__(self, event, context):
+ def __init__(self, event: AdminCliRequest, context: LambdaContext) -> None:
"""
Initializes handle instance
:param event: event to handle
@@ -30,7 +43,6 @@ def __init__(self, event, context):
"""
self._event = event
self._context = context
- self._logger = None
self.additional_parameters = {
"delete-period": {"exception_if_not_exists": True},
@@ -62,14 +74,18 @@ def __init__(self, event, context):
# Setup logging
classname = self.__class__.__name__
- dt = datetime.utcnow()
+ app_env = get_app_env()
+ dt = datetime.now(timezone.utc)
log_stream = LOG_STREAM.format(classname, dt.year, dt.month, dt.day)
self._logger = Logger(
- logstream=log_stream, buffersize=20, context=self._context
+ log_group=app_env.log_group,
+ log_stream=log_stream,
+ topic_arn=app_env.topic_arn,
+ debug=app_env.enable_debug_logging,
)
@property
- def action(self):
+ def action(self) -> Any:
"""
Retrieves admin REST api action from the event
:return: name of the action of the event
@@ -77,7 +93,7 @@ def action(self):
return self._event["action"]
@property
- def parameters(self):
+ def parameters(self) -> dict[Any, Any]:
params = self._event.get("parameters", {})
for p in params:
if p in self.transform_parameters:
@@ -88,7 +104,7 @@ def parameters(self):
return {p.replace("-", "_"): params[p] for p in params}
@staticmethod
- def is_handling_request(event):
+ def is_handling_request(event: Mapping[str, Any]) -> TypeGuard[AdminCliRequest]:
"""
Returns True if the handler can handle the event
:param event: tested event
@@ -99,14 +115,13 @@ def is_handling_request(event):
return False
return "action" in event
- # noinspection SpellCheckingInspection
- def handle_request(self):
+ def handle_request(self) -> Any:
"""
Handles the event
:return: result of handling the event, result send back to REST admin api
"""
- def snake_to_pascal_case(s):
+ def snake_to_pascal_case(s: Any) -> Any:
converted = ""
s = s.strip("_").capitalize()
i = 0
@@ -121,8 +136,7 @@ def snake_to_pascal_case(s):
return converted
- # noinspection PyShadowingNames
- def dict_to_pascal_case(d):
+ def dict_to_pascal_case(d: Any) -> Any:
d_result = {}
if isinstance(d, dict):
@@ -132,7 +146,7 @@ def dict_to_pascal_case(d):
return d_result
elif isinstance(d, list):
- return [dict_to_pascal_case(l) for l in d]
+ return [dict_to_pascal_case(item) for item in d]
return d
@@ -143,6 +157,10 @@ def dict_to_pascal_case(d):
json.dumps(self._event),
)
+ collect_metric(
+ CliRequestMetric(command_used=self.action), logger=self._logger
+ )
+
# get access to admin api
admin = ConfigAdmin(logger=self._logger, context=self._context)
@@ -156,7 +174,16 @@ def dict_to_pascal_case(d):
self._logger.info(
'Calling "{}" with parameters {}', fn.__name__, self.parameters
)
- api_result = fn(**self.parameters)
+
+ if fn.__name__ in [
+ "create_period",
+ "update_period",
+ "create_schedule",
+ "update_schedule",
+ ]:
+ api_result = fn(self.parameters)
+ else:
+ api_result = fn(**self.parameters)
# convert to awscli PascalCase output format
result = dict_to_pascal_case(api_result)
diff --git a/source/app/instance_scheduler/handler/collect_configuration_description.py b/source/app/instance_scheduler/handler/collect_configuration_description.py
new file mode 100644
index 00000000..91fe54db
--- /dev/null
+++ b/source/app/instance_scheduler/handler/collect_configuration_description.py
@@ -0,0 +1,121 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import dataclasses
+from datetime import datetime, timezone
+from typing import TYPE_CHECKING, Any, Literal, Mapping, TypedDict
+
+from typing_extensions import TypeGuard
+
+from instance_scheduler import configuration
+from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler.configuration.scheduler_config import GlobalConfig
+from instance_scheduler.handler.base import Handler
+from instance_scheduler.ops_metrics.metric_type.configuration_description_metric import (
+ ConfigurationDescriptionMetric,
+ ScheduleFlagCounts,
+)
+from instance_scheduler.ops_metrics.metrics import collect_metric
+from instance_scheduler.util.app_env import AppEnv, get_app_env
+from instance_scheduler.util.logger import Logger
+
+if TYPE_CHECKING:
+ from aws_lambda_powertools.utilities.typing import LambdaContext
+else:
+ LambdaContext = object
+
+
+class CollectConfigurationMetricsRequest(TypedDict):
+ scheduled_action: Literal["collect_configuration_metrics"]
+
+
+class CollectConfigurationDescription(Handler[CollectConfigurationMetricsRequest]):
+ def __init__(
+ self, event: CollectConfigurationMetricsRequest, context: LambdaContext
+ ) -> None:
+ self._context = context
+
+ # Setup logging
+ classname = self.__class__.__name__
+ app_env = get_app_env()
+ dt = datetime.now(timezone.utc)
+ logstream = "{}-{:0>4d}{:0>2d}{:0>2d}".format(
+ classname, dt.year, dt.month, dt.day
+ )
+ self._logger = Logger(
+ log_group=app_env.log_group,
+ log_stream=logstream,
+ topic_arn=app_env.topic_arn,
+ )
+
+ @staticmethod
+ def is_handling_request(
+ event: Mapping[str, Any]
+ ) -> TypeGuard[CollectConfigurationMetricsRequest]:
+ return str(event.get("scheduled_action", "")) == "collect_configuration_metrics"
+
+ def handle_request(self) -> Any:
+ with self._logger:
+ global_config = configuration.get_global_configuration(self._logger)
+ app_env = get_app_env()
+ metric = self.build_ops_metric(
+ global_config=global_config,
+ app_env=app_env,
+ lambda_context=self._context,
+ )
+
+ sent_metric = collect_metric(
+ metric,
+ logger=self._logger,
+ )
+
+ if sent_metric:
+ return {"sent_metric": dataclasses.asdict(sent_metric)}
+ else:
+ return {"sent_metric": {}}
+
+ @staticmethod
+ def build_ops_metric(
+ global_config: GlobalConfig,
+ app_env: AppEnv,
+ lambda_context: LambdaContext,
+ ) -> ConfigurationDescriptionMetric:
+ flag_counts = ScheduleFlagCounts()
+ for schedule in global_config.schedules.values():
+ flag_counts.stop_new_instances += schedule.stop_new_instances is True
+ flag_counts.enforced += schedule.enforced is True
+ flag_counts.retain_running += schedule.retain_running is True
+ flag_counts.hibernate += schedule.hibernate is True
+ flag_counts.override += schedule.override_status is not None
+ flag_counts.use_ssm_maintenance_window += (
+ schedule.use_maintenance_window is True
+ )
+ flag_counts.use_metrics += schedule.use_metrics is True
+ flag_counts.non_default_timezone += schedule.timezone != str(
+ global_config.default_timezone
+ )
+
+ metric = ConfigurationDescriptionMetric(
+ num_schedules=len(global_config.schedules),
+ num_cfn_schedules=CollectConfigurationDescription._count_cfn_schedules(
+ global_config.schedules
+ ),
+ schedule_flag_counts=flag_counts,
+ default_timezone=str(global_config.default_timezone),
+ schedule_aurora_clusters=global_config.schedule_clusters,
+ create_rds_snapshots=global_config.create_rds_snapshot,
+ schedule_interval_minutes=app_env.scheduler_frequency_minutes,
+ memory_size_mb=lambda_context.memory_limit_in_mb,
+ using_organizations=app_env.enable_aws_organizations,
+ enable_ec2_ssm_maintenance_windows=app_env.enable_ec2_ssm_maintenance_windows,
+ num_started_tags=len(app_env.start_tags),
+ num_stopped_tags=len(app_env.stop_tags),
+ )
+
+ return metric
+
+ @classmethod
+ def _count_cfn_schedules(cls, schedules: dict[str, InstanceSchedule]) -> int:
+ count = 0
+ for schedule in schedules.values():
+ count += bool(schedule.configured_in_stack)
+ return count
diff --git a/source/app/instance_scheduler/requesthandlers/scheduler_setup_handler.py b/source/app/instance_scheduler/handler/config_resource.py
similarity index 55%
rename from source/app/instance_scheduler/requesthandlers/scheduler_setup_handler.py
rename to source/app/instance_scheduler/handler/config_resource.py
index 53d253d8..b7f3426b 100644
--- a/source/app/instance_scheduler/requesthandlers/scheduler_setup_handler.py
+++ b/source/app/instance_scheduler/handler/config_resource.py
@@ -1,23 +1,65 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-
-import re
-import os
import json
-from copy import copy
-from datetime import datetime
-from hashlib import sha256
+import re
+from collections.abc import Mapping
+from datetime import datetime, timezone
+from re import Match
+from typing import TYPE_CHECKING, Any, Literal, Optional, TypedDict, TypeGuard
import boto3
from instance_scheduler import configuration
-from instance_scheduler.requesthandlers import setup_demo_data as demo_data
from instance_scheduler.boto_retry import get_client_with_standard_retry
-from instance_scheduler.configuration.config_admin import ConfigAdmin
-from instance_scheduler.util.custom_resource import CustomResource
+from instance_scheduler.configuration.config_admin import (
+ ConfigAdmin,
+ ConfigTableConfigItem,
+)
+from instance_scheduler.handler import setup_demo_data as demo_data
+from instance_scheduler.util.app_env import get_app_env
+from instance_scheduler.util.custom_resource import (
+ CustomResource,
+ CustomResourceRequest,
+)
from instance_scheduler.util.logger import Logger
-from instance_scheduler.util.metrics import allow_send_metrics, send_metrics_data
+
+if TYPE_CHECKING:
+ from aws_lambda_powertools.utilities.typing import LambdaContext
+ from mypy_boto3_logs import Client as LogsClient
+else:
+ LambdaContext = object
+ LogsClient = object
+
+BoolStr = Literal["True", "False"]
+
+
+class ServiceSetupResourceProperties(TypedDict):
+ ServiceToken: str # Lambda Function ARN
+ timeout: int
+ config_table: str # DynamoDB Table name
+ tagname: str # Schedule tag key
+ default_timezone: str
+ use_metrics: BoolStr
+ scheduled_services: list[str]
+ schedule_clusters: BoolStr
+ create_rds_snapshot: BoolStr
+ regions: list[str]
+ remote_account_ids: list[str]
+ namespace: str
+ aws_partition: str
+ scheduler_role_name: str
+ schedule_lambda_account: BoolStr
+ trace: BoolStr
+ enable_ssm_maintenance_windows: BoolStr
+ log_retention_days: float
+ started_tags: str
+ stopped_tags: str
+ stack_version: str
+ use_aws_organizations: BoolStr
+
+
+ServiceSetupRequest = CustomResourceRequest[ServiceSetupResourceProperties]
+
ERR_SETTING_CONFIG = "Error setting scheduler configuration {} "
ERR_SETTING_RETENTION_LAMBDA_LOGGROUP = (
@@ -35,37 +77,38 @@
LOG_STREAM = "{}-{:0>4d}{:0>2d}{:0>2d}"
-class SchedulerSetupHandler(CustomResource):
+class SchedulerSetupHandler(CustomResource[ServiceSetupResourceProperties]):
"""
Implements handler for setup helper in cloudformation
"""
- def __init__(self, event, context):
+ def __init__(self, event: Any, context: LambdaContext) -> None:
CustomResource.__init__(self, event, context)
# Setup logging
classname = self.__class__.__name__
- dt = datetime.utcnow()
+ app_env = get_app_env()
+ dt = datetime.now(timezone.utc)
log_stream = LOG_STREAM.format(classname, dt.year, dt.month, dt.day)
- self._logger = Logger(logstream=log_stream, buffersize=1, context=context)
-
- self.arguments = copy(self.resource_properties)
- self.arguments = {
- a: self.resource_properties[a]
- for a in self.resource_properties
- if a not in ["ServiceToken", "Timeout"]
- }
+ self._logger = Logger(
+ log_group=app_env.log_group,
+ log_stream=log_stream,
+ topic_arn=app_env.topic_arn,
+ debug=app_env.enable_debug_logging,
+ )
- self._stack_version = self.arguments["stack_version"]
+ self._stack_version = self.resource_properties["stack_version"]
@staticmethod
- def is_handling_request(event):
+ def is_handling_request(
+ event: Mapping[str, Any]
+ ) -> TypeGuard[CustomResourceRequest[ServiceSetupResourceProperties]]:
return (
event.get("StackId") is not None
and event.get("ResourceType") == "Custom::ServiceSetup"
)
@property
- def tagname(self):
+ def tagname(self) -> Any:
"""
Name of the tag to mark scheduled instances
:return: tag name
@@ -75,7 +118,7 @@ def tagname(self):
)
@property
- def default_timezone(self):
+ def default_timezone(self) -> Any:
"""
Returns default time zone
:return: default timezone
@@ -85,7 +128,7 @@ def default_timezone(self):
)
@property
- def use_metrics(self):
+ def use_metrics(self) -> Any:
"""
Returns global metrics switch
:return: metrics switch
@@ -93,7 +136,7 @@ def use_metrics(self):
return self.resource_properties.get(configuration.METRICS, "False")
@property
- def trace(self):
+ def trace(self) -> Any:
"""
Returns global trace flag
:return: trace flag
@@ -101,7 +144,7 @@ def trace(self):
return self.resource_properties.get(configuration.TRACE, "True")
@property
- def namespace(self):
+ def namespace(self) -> Any:
"""
Returns global namespace
:return: namespace string
@@ -109,7 +152,7 @@ def namespace(self):
return self.resource_properties.get(configuration.NAMESPACE, None)
@property
- def aws_partition(self):
+ def aws_partition(self) -> Any:
"""
Returns aws partition
:return: aws partition string
@@ -117,7 +160,7 @@ def aws_partition(self):
return self.resource_properties.get(configuration.AWS_PARTITION, None)
@property
- def scheduler_role_name(self):
+ def scheduler_role_name(self) -> Any:
"""
Returns execution_role_name
:return: execution_role_name string
@@ -125,32 +168,28 @@ def scheduler_role_name(self):
return self.resource_properties.get(configuration.SCHEDULER_ROLE_NAME, None)
@property
- def enable_SSM_maintenance_windows(self):
+ def enable_ssm_maintenance_windows(self) -> Any:
"""
Returns global enable SSM Maintenance Windows flag
- :return: ssm_enable_SSM_maintenance_windows flag
+ :return: ssm_enable_ssm_maintenance_windows flag
"""
return self.resource_properties.get(
configuration.ENABLE_SSM_MAINTENANCE_WINDOWS, "False"
)
@property
- def regions(self):
+ def regions(self) -> set[str] | list[str]:
"""
Returns all regions from the configuration
:return: regions
"""
- result = set(self.resource_properties.get(configuration.REGIONS))
- if (
- result is None
- or result == set()
- or len([i for i in result if i.strip() != ""]) == 0
- ):
+ result: set[str] | list[str] = set(self.resource_properties["regions"])
+ if result == set() or len([i for i in result if i.strip() != ""]) == 0:
result = [boto3.Session().region_name]
return result
@property
- def started_tags(self):
+ def started_tags(self) -> Any:
"""
Returns started tags as a string
:return: started tags
@@ -158,7 +197,7 @@ def started_tags(self):
return self.resource_properties.get(configuration.STARTED_TAGS, None)
@property
- def stopped_tags(self):
+ def stopped_tags(self) -> Any:
"""
Returns stopped tags as a string
:return: stopped tags
@@ -166,63 +205,43 @@ def stopped_tags(self):
return self.resource_properties.get(configuration.STOPPED_TAGS, None)
@property
- def remote_account_ids(self):
+ def remote_account_ids(self) -> Any:
"""
Returns remote account ids
:return: remote account ids
"""
- result = set(self.resource_properties.get(configuration.REMOTE_ACCOUNT_IDS))
- if (
- result is None
- or result == set()
- or len([i for i in result if i.strip() != ""]) == 0
- ):
- return None
-
- return result
-
- @property
- def remote_account_ids(self):
- """
- Returns remote account ids
- :return: remote account ids
- """
- result = set(self.resource_properties.get(configuration.REMOTE_ACCOUNT_IDS))
+ result = set(self.resource_properties["remote_account_ids"])
if result == set() or len([i for i in result if i.strip() != ""]) == 0:
return None
return result
@property
- def old_remote_account_ids(self):
+ def old_remote_account_ids(self) -> Any:
"""
Returns remote account ids from the previous event of create/update
:return: remote account ids
"""
- result = set(self.old_resource_properties.get(configuration.REMOTE_ACCOUNT_IDS))
+ result = set(self.old_resource_properties["remote_account_ids"])
if result == set() or len([i for i in result if i.strip() != ""]) == 0:
return None
return result
@property
- def scheduled_services(self):
+ def scheduled_services(self) -> Optional[set[str]]:
"""
Returns scheduled services
:return: services to schedule
"""
- result = set(self.resource_properties.get(configuration.SCHEDULED_SERVICES))
- if (
- result is None
- or result == set()
- or len([i for i in result if i.strip() != ""]) == 0
- ):
+ result = set(self.resource_properties["scheduled_services"])
+ if result == set() or len([i for i in result if i.strip() != ""]) == 0:
return None
return result
@property
- def schedule_clusters(self):
+ def schedule_clusters(self) -> Any:
"""
Returns global schedule clusters flag
:return: schedule_clusters flag
@@ -230,7 +249,7 @@ def schedule_clusters(self):
return self.resource_properties.get(configuration.SCHEDULE_CLUSTERS, "False")
@property
- def create_rds_snapshot(self):
+ def create_rds_snapshot(self) -> Any:
"""
Returns global create RDS Snapshots flag
:return: create_rds_snapshot flag
@@ -238,7 +257,7 @@ def create_rds_snapshot(self):
return self.resource_properties.get(configuration.CREATE_RDS_SNAPSHOT, "True")
@property
- def schedule_lambda_account(self):
+ def schedule_lambda_account(self) -> Any:
"""
Returns flag for processing lambda account switch
:return: lambda account process switch
@@ -248,7 +267,7 @@ def schedule_lambda_account(self):
)
@property
- def use_aws_organizations(self):
+ def use_aws_organizations(self) -> Any:
"""
Returns use_aws_organizations flag
:return: use_aws_organizations flag
@@ -257,7 +276,7 @@ def use_aws_organizations(self):
configuration.USE_AWS_ORGANIZATIONS, "False"
)
- def handle_request(self):
+ def handle_request(self) -> None:
"""
Handles the custom resource request to write scheduler global settings to config database
:return:
@@ -273,17 +292,17 @@ def handle_request(self):
finally:
self._logger.flush()
- def get_valid_org_id(self, org_id):
+ def get_valid_org_id(self, org_id: str) -> Optional[Match[str]]:
"""
Verifies if the ou_id param is a valid ou_id format. https://docs.aws.amazon.com/organizations/latest/APIReference/API_Organization.html
:return: the org id or else None
"""
- try:
- return re.fullmatch("^o-[a-z0-9]{10,32}$", org_id)
- except Exception as error:
- raise error
+ return re.fullmatch("^o-[a-z0-9]{10,32}$", org_id)
+
+ def _update_settings(self, prev_org_remote_account_ids: Any = None) -> bool:
+ if prev_org_remote_account_ids is None:
+ prev_org_remote_account_ids = {}
- def _update_settings(self, prev_org_remote_account_ids={}):
try:
admin = ConfigAdmin(logger=self._logger, context=self.context)
try:
@@ -305,24 +324,27 @@ def _update_settings(self, prev_org_remote_account_ids={}):
remote_account_ids = self.remote_account_ids
settings = admin.update_config(
- default_timezone=self.default_timezone,
- scheduled_services=self.scheduled_services,
- schedule_clusters=self.schedule_clusters,
- create_rds_snapshot=self.create_rds_snapshot,
- tagname=self.tagname,
- regions=self.regions,
- remote_account_ids=remote_account_ids,
- organization_id=self.organization_id,
- schedule_lambda_account=self.schedule_lambda_account.lower() == "true",
- use_metrics=self.use_metrics.lower() == "true",
- trace=self.trace.lower() == "true",
- enable_SSM_maintenance_windows=self.enable_SSM_maintenance_windows.lower()
- == "true",
- scheduler_role_name=self.scheduler_role_name,
- aws_partition=self.aws_partition,
- namespace=self.namespace,
- started_tags=self.started_tags,
- stopped_tags=self.stopped_tags,
+ ConfigTableConfigItem(
+ default_timezone=self.default_timezone,
+ scheduled_services=self.scheduled_services or set(),
+ schedule_clusters=self.schedule_clusters,
+ create_rds_snapshot=self.create_rds_snapshot,
+ tagname=self.tagname,
+ regions=self.regions,
+ remote_account_ids=remote_account_ids,
+ organization_id=self.organization_id,
+ schedule_lambda_account=self.schedule_lambda_account.lower()
+ == "true",
+ use_metrics=self.use_metrics.lower() == "true",
+ trace=self.trace.lower() == "true",
+ enable_ssm_maintenance_windows=self.enable_ssm_maintenance_windows.lower()
+ == "true",
+ scheduler_role_name=self.scheduler_role_name,
+ aws_partition=self.aws_partition,
+ namespace=self.namespace,
+ started_tags=self.started_tags,
+ stopped_tags=self.stopped_tags,
+ )
)
self._logger.info(INF_CONFIG_SET, str(settings))
@@ -333,87 +355,58 @@ def _update_settings(self, prev_org_remote_account_ids={}):
return True
- def set_lambda_logs_retention_period(self):
+ def set_lambda_logs_retention_period(self) -> None:
"""
- Aligns retention period for default Lambda log streams with settings
- :return:
+ Sets the retention period of the log group associated with the Lambda context to
+ - resource_properties["log_retention_days"] if present
+ - default value of 30 otherwise
"""
+ if not self.context:
+ return
- if self.context is None:
- return True
-
- loggroup = self.context.log_group_name
- log_client = get_client_with_standard_retry("logs")
- retention_days = self.arguments.get("log_retention_days", 30)
+ loggroup: str = self.context.log_group_name
+ log_client: LogsClient = get_client_with_standard_retry("logs")
+ retention_days = int(self.resource_properties.get("log_retention_days", 30))
try:
- if retention_days is None:
- self._logger.info(INFO_DELETE_LOG_RETENTION_POLICY, loggroup)
- log_client.delete_retention_policy(loggroup)
- return True
- else:
- self._logger.info(
- INFO_SET_LOG_RETENTION_POLICY, loggroup, retention_days
- )
- log_client.put_retention_policy(
- logGroupName=loggroup, retentionInDays=int(retention_days)
- )
- return True
+ self._logger.info(INFO_SET_LOG_RETENTION_POLICY, loggroup, retention_days)
+ log_client.put_retention_policy(
+ logGroupName=loggroup, retentionInDays=int(retention_days)
+ )
except Exception as ex:
self._logger.warning(
ERR_SETTING_RETENTION_LAMBDA_LOGGROUP,
self.context.log_group_name,
str(ex),
)
- return True
- def _create_sample_schemas(self):
+ def _create_sample_schemas(self) -> None:
try:
admin: ConfigAdmin = ConfigAdmin(logger=self._logger, context=self.context)
- admin.create_period(**demo_data.PERIOD_WORKING_DAYS)
- admin.create_period(**demo_data.PERIOD_WEEKENDS)
- admin.create_period(**demo_data.PERIOD_OFFICE_HOURS)
- admin.create_period(**demo_data.PERIOD_FIRST_MONDAY_IN_QUARTER)
+ admin.create_period(demo_data.PERIOD_WORKING_DAYS)
+ admin.create_period(demo_data.PERIOD_WEEKENDS)
+ admin.create_period(demo_data.PERIOD_OFFICE_HOURS)
+ admin.create_period(demo_data.PERIOD_FIRST_MONDAY_IN_QUARTER)
- admin.create_schedule(**demo_data.SCHEDULE_SEATTLE_OFFICE_HOURS)
- admin.create_schedule(**demo_data.SCHEDULE_UK_OFFICE_HOURS)
- admin.create_schedule(**demo_data.SCHEDULE_STOPPED)
- admin.create_schedule(**demo_data.SCHEDULE_RUNNING)
- admin.create_schedule(**demo_data.SCHEDULE_SCALING)
+ admin.create_schedule(demo_data.SCHEDULE_SEATTLE_OFFICE_HOURS)
+ admin.create_schedule(demo_data.SCHEDULE_UK_OFFICE_HOURS)
+ admin.create_schedule(demo_data.SCHEDULE_STOPPED)
+ admin.create_schedule(demo_data.SCHEDULE_RUNNING)
+ admin.create_schedule(demo_data.SCHEDULE_SCALING)
except Exception as ex:
self._logger.error(
"Error creating sample schedules and periods {}".format(ex)
)
- def _send_create_metrics(self):
- metrics_data = {
- "Type": "stack",
- "Version": self._stack_version,
- "StackHash": sha256(self.stack_id.encode("utf-8")).hexdigest(),
- "Data": {"Status": "stack_create", "Region": self.region},
- }
-
- send_metrics_data(metrics=metrics_data, logger=self._logger)
-
- def _send_delete_metrics(self):
- metrics_data = {
- "Type": "stack",
- "Version": self._stack_version,
- "StackHash": sha256(self.stack_id.encode("utf-8")).hexdigest(),
- "Data": {"Status": "stack_delete", "Region": self.region},
- }
-
- send_metrics_data(metrics=metrics_data, logger=self._logger)
-
# handles Create request from CloudFormation
- def _create_request(self):
- if allow_send_metrics():
- self._send_create_metrics()
+ def _create_request(self) -> bool:
self._create_sample_schemas()
- return self._update_settings() and self.set_lambda_logs_retention_period()
+ result = self._update_settings()
+ self.set_lambda_logs_retention_period()
+ return result
- def _update_request(self):
+ def _update_request(self) -> bool:
try:
org_id = list(self.remote_account_ids)[0]
except Exception as error:
@@ -431,17 +424,14 @@ def _update_request(self):
and self.get_valid_org_id(prev_org_id)
and org_id == prev_org_id
):
- config = configuration.get_scheduler_configuration(self._logger)
+ config = configuration.get_global_configuration(self._logger)
prev_remote_account_id = config.remote_account_ids
else:
- prev_remote_account_id = {}
- return (
- self._update_settings(prev_remote_account_id)
- and self.set_lambda_logs_retention_period()
- )
+ prev_remote_account_id = []
+ result = self._update_settings(prev_remote_account_id)
+ self.set_lambda_logs_retention_period()
+ return result
# handles Delete request from CloudFormation
- def _delete_request(self):
- if allow_send_metrics():
- self._send_delete_metrics()
+ def _delete_request(self) -> bool:
return True
diff --git a/source/app/instance_scheduler/handler/scheduling_orchestrator.py b/source/app/instance_scheduler/handler/scheduling_orchestrator.py
new file mode 100644
index 00000000..09e4f1c4
--- /dev/null
+++ b/source/app/instance_scheduler/handler/scheduling_orchestrator.py
@@ -0,0 +1,266 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import json
+from collections.abc import Iterator, Mapping
+from datetime import datetime, timezone
+from typing import TYPE_CHECKING, Any, Literal, Optional, TypedDict, TypeGuard
+
+import boto3
+
+from instance_scheduler import configuration
+from instance_scheduler.boto_retry import get_client_with_standard_retry
+from instance_scheduler.configuration.scheduler_config import GlobalConfig
+from instance_scheduler.configuration.scheduling_context import SchedulingContext
+from instance_scheduler.handler.base import Handler
+from instance_scheduler.ops_metrics.metric_type.deployment_description_metric import (
+ DeploymentDescriptionMetric,
+)
+from instance_scheduler.ops_metrics.metrics import collect_metric
+from instance_scheduler.util.app_env import get_app_env
+from instance_scheduler.util.logger import Logger
+
+if TYPE_CHECKING:
+ from aws_lambda_powertools.utilities.typing import LambdaContext
+else:
+ LambdaContext = object
+ STSClient = object
+
+LOG_STREAM = "{}-{:0>4d}{:0>2d}{:0>2d}"
+LOG_STREAM_PREFIX = "Scheduler"
+
+
+class OrchestrationRequest(TypedDict):
+ scheduled_action: Literal["run_orchestrator"]
+
+
+LAMBDA_PAYLOAD_CAPACITY_BYTES = (
+ 200_000 # is actually 256_000 but this provides some overhead
+)
+
+
+class SchedulingOrchestratorHandler(Handler[OrchestrationRequest]):
+ """
+ Handles event from cloudwatch rule timer
+ """
+
+ def __init__(self, event: OrchestrationRequest, context: LambdaContext) -> None:
+ self._context = context
+ self._event = event
+ self._configuration: Optional[GlobalConfig] = None
+ self._lambda_client = None
+ self._hub_account_id: str = context.invoked_function_arn.split(":")[4]
+
+ # Setup logging
+ classname = self.__class__.__name__
+ app_env = get_app_env()
+ dt = datetime.now(timezone.utc)
+ logstream = LOG_STREAM.format(classname, dt.year, dt.month, dt.day)
+ self._logger = Logger(
+ log_group=app_env.log_group,
+ log_stream=logstream,
+ topic_arn=app_env.topic_arn,
+ debug=app_env.enable_debug_logging,
+ )
+
+ @property
+ def lambda_client(self) -> Any:
+ """
+ Get the lambda client
+ :return: lambda client
+ """
+ if self._lambda_client is None:
+ self._lambda_client = get_client_with_standard_retry("lambda")
+ return self._lambda_client
+
+ @property
+ def configuration(self) -> GlobalConfig:
+ """
+ Returns the scheduler configuration
+ :return: scheduler configuration
+ """
+ if self._configuration is None:
+ self._configuration = configuration.get_global_configuration(self._logger)
+ return self._configuration
+
+ def accounts_and_roles(self, config: GlobalConfig) -> Iterator[str]:
+ """
+ Iterates account and cross-account-roles of the accounts to operate on
+ :return:
+ """
+ processed_accounts = []
+
+ if config.schedule_lambda_account:
+ processed_accounts.append(self._hub_account_id)
+ yield self._hub_account_id
+
+ for remote_account in config.remote_account_ids:
+ if remote_account is None:
+ continue
+ # warn and skip if account was already processed
+ if remote_account in processed_accounts:
+ self._logger.warning(
+ "Remote account {} is already processed", remote_account
+ )
+ continue
+ yield remote_account
+
+ def target_account_id(self, context: SchedulingContext) -> str:
+ """
+ Iterates list of accounts to process
+ :param context:
+ :return:
+ """
+ if context.schedule_lambda_account:
+ return self._hub_account_id
+ else:
+ return context.account_id
+
+ @staticmethod
+ def is_handling_request(
+ event: Mapping[str, Any]
+ ) -> TypeGuard[OrchestrationRequest]:
+ """
+ Handler for cloudwatch event to run the scheduler
+ :return: True
+ """
+ return str(event.get("scheduled_action", "")) == "run_orchestrator"
+
+ def handle_request(self) -> list[Any]:
+ """
+ Handles the CloudWatch Rule timer events
+ :return:
+ """
+ try:
+ self._logger.info(
+ "Handler {} : Received request {} at {}",
+ self.__class__.__name__,
+ json.dumps(self._event),
+ datetime.now(),
+ )
+
+ result = []
+ for scheduling_context in self.list_scheduling_contexts(self.configuration):
+ result.append(self._run_scheduling_lambda(scheduling_context))
+
+ collect_metric(
+ DeploymentDescriptionMetric(
+ services=self.configuration.scheduled_services,
+ regions=self.configuration.regions,
+ num_accounts=sum(
+ 1 for _ in self.accounts_and_roles(self.configuration)
+ ),
+ ),
+ logger=self._logger,
+ )
+
+ return result
+ finally:
+ self._logger.flush()
+
+ def list_scheduling_contexts(
+ self, config: GlobalConfig
+ ) -> Iterator[SchedulingContext]:
+ services = config.scheduled_services
+ regions = config.regions
+ current_dt = datetime.now(timezone.utc)
+ if not regions:
+ regions = [boto3.Session().region_name]
+ # todo: better way to use local region?
+ # todo: could pull from event the same as how lambda_account is fetched
+
+ for service in services:
+ for region in regions:
+ for account in self.accounts_and_roles(
+ config
+ ): # todo: pull from config.remote_accounts directly?
+ if account is self._hub_account_id: # local account
+ schedule_lambda_account = True
+ account_id = ""
+ else: # remote account
+ schedule_lambda_account = False
+ account_id = account
+
+ yield SchedulingContext(
+ account_id=account_id, # mutated above
+ service=service,
+ region=region,
+ current_dt=current_dt,
+ schedules=config.schedules,
+ default_timezone=config.default_timezone,
+ schedule_clusters=config.schedule_clusters,
+ tag_name=config.tag_name,
+ trace=config.trace,
+ enable_ssm_maintenance_windows=config.enable_ssm_maintenance_windows,
+ use_metrics=config.use_metrics,
+ namespace=config.namespace,
+ aws_partition=config.aws_partition,
+ scheduler_role_name=config.scheduler_role_name,
+ organization_id=config.organization_id,
+ schedule_lambda_account=schedule_lambda_account, # mutated above
+ create_rds_snapshot=config.create_rds_snapshot,
+ started_tags=config.started_tags, #
+ stopped_tags=config.stopped_tags,
+ )
+
+ def _run_scheduling_lambda(self, context: SchedulingContext) -> dict[str, Any]:
+ # runs a service/account/region subset of the configuration as a new lambda function
+ self._logger.info(
+ "Starting lambda function for scheduling {} instances for account {} in region {}",
+ context.service,
+ self.target_account_id(context),
+ context.region,
+ )
+
+ # need to convert configuration to dictionary to allow it to be passed in event
+ event_payload = context.to_dict()
+
+ payload = str.encode(
+ json.dumps(
+ {
+ "action": "scheduler:run",
+ "configuration": event_payload,
+ "dispatch_time": str(datetime.now()),
+ }
+ )
+ )
+
+ if len(payload) > LAMBDA_PAYLOAD_CAPACITY_BYTES:
+ strip_schedules_and_periods(event_payload)
+ payload = str.encode(
+ json.dumps(
+ {
+ "action": "scheduler:run",
+ "configuration": event_payload,
+ "dispatch_time": str(datetime.now()),
+ }
+ )
+ )
+
+ # start the lambda function
+ resp = self.lambda_client.invoke(
+ FunctionName=self._context.function_name,
+ InvocationType="Event",
+ LogType="None",
+ Payload=payload,
+ )
+ if resp["StatusCode"] != 202:
+ self._logger.error(
+ "Error executing {}, version {} with configuration {}",
+ self._context.function_name,
+ self._context.function_version,
+ event_payload,
+ )
+
+ result = {
+ "service": context.service,
+ "account": self.target_account_id(context),
+ "region": context.region,
+ "lambda_invoke_result": resp["StatusCode"],
+ "lambda_request_id": resp["ResponseMetadata"]["RequestId"],
+ }
+ return result
+
+
+def strip_schedules_and_periods(event_dict: dict[str, Any]) -> None:
+ event_dict["schedules"] = {}
+ event_dict["periods"] = {}
diff --git a/source/app/instance_scheduler/handler/scheduling_request.py b/source/app/instance_scheduler/handler/scheduling_request.py
new file mode 100644
index 00000000..57029e3e
--- /dev/null
+++ b/source/app/instance_scheduler/handler/scheduling_request.py
@@ -0,0 +1,286 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import dataclasses
+import json
+from collections.abc import Mapping
+from datetime import datetime
+from typing import TYPE_CHECKING, Any, Final, Literal, Optional, TypedDict, TypeGuard
+
+import boto3
+from boto3 import Session
+from botocore.exceptions import ClientError
+
+from instance_scheduler import configuration
+from instance_scheduler.configuration import scheduling_context
+from instance_scheduler.handler.base import Handler
+from instance_scheduler.schedulers.instance_scheduler import InstanceScheduler
+from instance_scheduler.schedulers.instance_states import InstanceStates
+from instance_scheduler.service import ServiceArgs, services
+from instance_scheduler.util import get_boto_config
+from instance_scheduler.util.app_env import get_app_env
+from instance_scheduler.util.logger import Logger
+
+if TYPE_CHECKING:
+ from aws_lambda_powertools.utilities.typing import LambdaContext
+ from mypy_boto3_lambda.client import LambdaClient
+ from mypy_boto3_sts.client import STSClient
+else:
+ LambdaContext = object
+ LambdaClient = object
+ STSClient = object
+
+
+class SchedulerRequest(TypedDict):
+ action: Literal["scheduler:run"]
+ configuration: dict[str, Any]
+ dispatch_time: str
+
+
+class SchedulingRequestHandler(Handler[SchedulerRequest]):
+ def __init__(self, event: SchedulerRequest, context: LambdaContext) -> None:
+ self._function_name: Final = context.function_name
+ self._hub_account_id: Final = context.invoked_function_arn.split(":")[4]
+ self._scheduling_context = scheduling_context.from_dict(event["configuration"])
+ self._target_account_id: Final = (
+ self._hub_account_id
+ if self._scheduling_context.schedule_lambda_account
+ else self._scheduling_context.account_id
+ )
+
+ self._sts_client: Optional[STSClient] = None
+ self._lambda_client: Optional[LambdaClient] = None
+
+ app_env: Final = get_app_env()
+
+ self._state_table_name: Final = app_env.state_table_name
+ self._stack_name: Final = app_env.stack_name
+
+ log_stream_name: Final = "-".join(
+ [
+ "Scheduler",
+ self._scheduling_context.service,
+ self._target_account_id,
+ self._scheduling_context.region,
+ ]
+ )
+ dt: Final = datetime.now(self._scheduling_context.default_timezone)
+ log_stream: Final = "{}-{:0>4d}{:0>2d}{:0>2d}".format(
+ log_stream_name, dt.year, dt.month, dt.day
+ )
+ self._logger: Final = Logger(
+ log_group=app_env.log_group,
+ log_stream=log_stream,
+ topic_arn=app_env.topic_arn,
+ debug=app_env.enable_debug_logging,
+ )
+
+ if self._scheduling_context.schedules == {}:
+ # for large configurations the schedules are not passed in the event, so we
+ # need to reload them from dynamo
+ global_config = configuration.get_global_configuration(self._logger)
+ self._scheduling_context = dataclasses.replace(
+ self._scheduling_context, schedules=global_config.schedules
+ )
+
+ @staticmethod
+ def is_handling_request(event: Mapping[str, Any]) -> TypeGuard[SchedulerRequest]:
+ return str(event.get("action", "")) == "scheduler:run"
+
+ def handle_request(self) -> Any:
+ with self._logger:
+ message: Final = (
+ "Handler {} scheduling request for service {}, account {}, region {} "
+ "at {}, time stamp is based on the default timezone selected for the "
+ "solution."
+ )
+ self._logger.info(
+ message.format(
+ self.__class__.__name__,
+ self._scheduling_context.service,
+ self._target_account_id,
+ self._scheduling_context.region,
+ datetime.now(self._scheduling_context.default_timezone),
+ )
+ )
+
+ service_args: Final = ServiceArgs(
+ account_id=self._target_account_id,
+ logger=self._logger,
+ stack_name=self._stack_name,
+ session=self.get_session_for_target_account(),
+ scheduling_context=self._scheduling_context,
+ )
+
+ service_name: Final = self._scheduling_context.service
+
+ service_strategy: Final = services[service_name](service_args)
+
+ instance_states: Final = InstanceStates(
+ self._state_table_name, service_name, self._logger
+ )
+
+ scheduler: Final = InstanceScheduler(
+ service_strategy,
+ self._scheduling_context,
+ instance_states,
+ self._target_account_id,
+ self.get_role_arn(),
+ self._logger,
+ )
+
+ result: Final = {self._target_account_id: scheduler.run()}
+
+ self._logger.info("Scheduler result {}", result)
+
+ return result
+
+ @property
+ def sts(self) -> STSClient:
+ if self._sts_client is None:
+ session: Final = Session()
+ sts_regional_endpoint: Final = str.format(
+ "https://sts.{}.amazonaws.com", session.region_name
+ )
+ # STS client __must__ use a regional endpoint so that tokens are version 2.
+ # version 1 tokens are not valid in opt-in regions unless enabled on an
+ # account level
+ self._sts_client = session.client(
+ "sts",
+ region_name=session.region_name,
+ endpoint_url=sts_regional_endpoint,
+ config=get_boto_config(),
+ )
+ return self._sts_client
+
+ def targeting_hub_account(self) -> bool:
+ return self._target_account_id == self._hub_account_id
+
+ def get_session_for_target_account(self) -> Session:
+ if self.targeting_hub_account():
+ return Session(region_name=self._scheduling_context.region)
+ else:
+ return self.get_session_for_spoke_account()
+
+ def get_role_arn(self) -> Optional[str]:
+ if self.targeting_hub_account():
+ # no role in the hub account
+ return None
+ else:
+ spoke_account_role_name: Final = "-".join(
+ [
+ self._scheduling_context.namespace,
+ self._scheduling_context.scheduler_role_name,
+ ]
+ )
+ return ":".join(
+ [
+ "arn",
+ self._scheduling_context.aws_partition,
+ "iam",
+ "",
+ self._target_account_id,
+ f"role/{spoke_account_role_name}",
+ ]
+ )
+
+ def get_session_for_spoke_account(self) -> Session:
+ spoke_account_role_arn: Final = self.get_role_arn()
+ if not spoke_account_role_arn:
+ raise ValueError("No role to assume")
+
+ # get a token for the cross account role and use it to create a session
+ try:
+ session_name: Final = "{}-scheduler-{}".format(
+ self._scheduling_context.service, self._target_account_id
+ )
+ # assume a role
+ token: Final = self.sts.assume_role(
+ RoleArn=spoke_account_role_arn, RoleSessionName=session_name
+ )
+ credentials: Final = token["Credentials"]
+ # create a session using the assumed role credentials
+ return Session(
+ aws_access_key_id=credentials["AccessKeyId"],
+ aws_secret_access_key=credentials["SecretAccessKey"],
+ aws_session_token=credentials["SessionToken"],
+ region_name=self._scheduling_context.region,
+ )
+ except ClientError as ex:
+ self._logger.error(
+ "Error Code {}".format(ex.response.get("Error", {}).get("Code"))
+ )
+ if ex.response.get("Error", {}).get("Code") == "AccessDenied":
+ self.remove_account_from_config(
+ aws_account=self._target_account_id,
+ cross_account_role=spoke_account_role_arn,
+ )
+ else:
+ self._logger.error(
+ "Can not assume role {} for account {}, ({}))".format(
+ spoke_account_role_arn, self._target_account_id, str(ex)
+ )
+ )
+ raise RuntimeError(
+ "Unable to assume role {} for account {}".format(
+ spoke_account_role_arn, self._target_account_id
+ )
+ )
+
+ @property
+ def lambda_client(self) -> LambdaClient:
+ if self._lambda_client is None:
+ self._lambda_client = boto3.client("lambda", config=get_boto_config())
+ return self._lambda_client
+
+ def remove_account_from_config(
+ self, aws_account: str, cross_account_role: str
+ ) -> None:
+ """
+ This method will invoke the lambda to remove the aws_account from the
+ configuration, it calls the lambda handler eventbus_request_handler, and sends
+ payload which will update the config by removing the account from further
+ scheduling.
+ {
+ "account": 111122223333,
+ "detail-type": "Parameter Store Change",
+ "detail": {
+ "operation": "Delete"
+ }
+ }
+ :param aws_account: account where the assume role permission is not available
+ for the lambda role to assume.
+ :param cross_account_role: role name for logging message to SNS.
+ """
+ try:
+ message: Final = (
+ "Removing the account {} from scheduling configuration as assume role "
+ "permission is missing for the iam role {}"
+ )
+ self._logger.error(message.format(aws_account, cross_account_role))
+ payload: Final = str.encode(
+ json.dumps(
+ {
+ "account": aws_account,
+ "detail-type": "Parameter Store Change",
+ "detail": {"operation": "Delete"},
+ }
+ )
+ )
+ response: Final = self.lambda_client.invoke(
+ FunctionName=self._function_name,
+ InvocationType="Event",
+ LogType="None",
+ Payload=payload,
+ )
+ self._logger.info(
+ "Removing account {} from configuration".format(aws_account)
+ )
+ self._logger.debug(
+ "Lambda response {} for removing account from configuration".format(
+ response
+ )
+ )
+ except Exception as ex:
+ self._logger.error(
+ "Error invoking lambda {} error {}".format(self._function_name, ex)
+ )
diff --git a/source/app/instance_scheduler/handler/setup_demo_data.py b/source/app/instance_scheduler/handler/setup_demo_data.py
new file mode 100644
index 00000000..c947235c
--- /dev/null
+++ b/source/app/instance_scheduler/handler/setup_demo_data.py
@@ -0,0 +1,61 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from instance_scheduler.configuration.config_admin import (
+ ConfigTablePeriodItem,
+ ConfigTableScheduleItem,
+)
+
+PERIOD_WORKING_DAYS = ConfigTablePeriodItem(
+ name="working-days",
+ description="Working days",
+ weekdays={"mon-fri"},
+)
+PERIOD_WEEKENDS = ConfigTablePeriodItem(
+ name="weekends",
+ description="Days in weekend",
+ weekdays={"sat-sun"},
+)
+PERIOD_OFFICE_HOURS = ConfigTablePeriodItem(
+ name="office-hours",
+ description="Office hours",
+ weekdays={"mon-fri"},
+ begintime="09:00",
+ endtime="17:00",
+)
+PERIOD_FIRST_MONDAY_IN_QUARTER = ConfigTablePeriodItem(
+ name="first-monday-in-quarter",
+ description="Every first monday of each quarter",
+ weekdays={"mon#1"},
+ months={"jan/3"},
+)
+
+SCHEDULE_SEATTLE_OFFICE_HOURS = ConfigTableScheduleItem(
+ name="seattle-office-hours",
+ description="Office hours in Seattle (Pacific)",
+ periods={"office-hours"},
+ timezone="US/Pacific",
+)
+SCHEDULE_UK_OFFICE_HOURS = ConfigTableScheduleItem(
+ name="uk-office-hours",
+ description="Office hours in UK",
+ periods={"office-hours"},
+ timezone="Europe/London",
+)
+SCHEDULE_STOPPED = ConfigTableScheduleItem(
+ name="stopped",
+ description="Instances stopped",
+ override_status="stopped",
+ use_metrics=False,
+)
+SCHEDULE_RUNNING = ConfigTableScheduleItem(
+ name="running",
+ description="Instances running",
+ override_status="running",
+ use_metrics=False,
+)
+SCHEDULE_SCALING = ConfigTableScheduleItem(
+ name="scale-up-down",
+ description="Vertical scaling on weekdays, based on UTC time",
+ periods={"working-days@t2.micro", "weekends@t2.nano"},
+ timezone="UTC",
+)
diff --git a/source/app/instance_scheduler/requesthandlers/eventbus_request_handler.py b/source/app/instance_scheduler/handler/spoke_registration.py
similarity index 73%
rename from source/app/instance_scheduler/requesthandlers/eventbus_request_handler.py
rename to source/app/instance_scheduler/handler/spoke_registration.py
index fb1d7425..c92250a9 100644
--- a/source/app/instance_scheduler/requesthandlers/eventbus_request_handler.py
+++ b/source/app/instance_scheduler/handler/spoke_registration.py
@@ -1,12 +1,19 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-import os
import json
-from instance_scheduler import configuration
-from datetime import datetime
-from instance_scheduler.util.logger import Logger
+from collections.abc import Mapping
+from datetime import datetime, timezone
+from typing import TYPE_CHECKING, Any, TypeGuard
+
+from instance_scheduler.handler.base import Handler
+from instance_scheduler.util.app_env import get_app_env
from instance_scheduler.util.dynamodb_utils import DynamoDBUtils
+from instance_scheduler.util.logger import Logger
+
+if TYPE_CHECKING:
+ from aws_lambda_powertools.utilities.typing import LambdaContext
+else:
+ LambdaContext = object
INF_HANDLER = "Request Handler {} : Received request {} at {}"
@@ -14,42 +21,45 @@
EVENT_CREATE = "Create"
EVENT_DELETE = "Delete"
+SpokeRegistrationRequest = dict[str, Any]
+
-class EventBusRequestHandler:
+class SpokeRegistrationHandler(Handler[SpokeRegistrationRequest]):
"""
Handles event from cloudwatch rule time
"""
- def __init__(self, event, context):
+ def __init__(self, event: SpokeRegistrationRequest, context: LambdaContext) -> None:
self._context = context
self._event = event
self._configuration = None
self._lambda_client = None
- self._config_table_name = os.getenv(configuration.ENV_CONFIG)
- # Setup logging
- self._is_trace_enabled = os.getenv("TRACE", False)
logging_stream_name = "-".join(["eventbus_request_handler"])
- dt = datetime.utcnow()
- logstream = "{}-{:0>4d}{:0>2d}{:0>2d}".format(
+ dt = datetime.now(timezone.utc)
+ app_env = get_app_env()
+ self._config_table_name = app_env.config_table_name
+ log_stream = "{}-{:0>4d}{:0>2d}{:0>2d}".format(
logging_stream_name, dt.year, dt.month, dt.day
)
self._logger = Logger(
- logstream=logstream,
- buffersize=60 if self._is_trace_enabled else 30,
- context=self._context,
- debug=self._is_trace_enabled,
+ log_group=app_env.log_group,
+ log_stream=log_stream,
+ topic_arn=app_env.topic_arn,
+ debug=app_env.enable_debug_logging,
)
@staticmethod
- def is_handling_request(event):
+ def is_handling_request(
+ event: Mapping[str, Any]
+ ) -> TypeGuard[SpokeRegistrationRequest]:
"""
Handler for EventBus request to update accounts.
:return: True
"""
- return event.get("detail-type", "") == "Parameter Store Change"
+ return str(event.get("detail-type", "")) == "Parameter Store Change"
- def handle_request(self):
+ def handle_request(self) -> str:
"""
Handles the CloudWatch Rule timer events
:return:
@@ -69,7 +79,7 @@ def handle_request(self):
)
config_key = {"name": "scheduler", "type": "config"}
if detail.get("operation") == EVENT_CREATE:
- self._logger.info(f"Add account id from the config")
+ self._logger.info("Add account id from the config")
account = self._event.get("account")
update_account_ids_response = dynamodb_table.update_item(
TableName=self._config_table_name,
@@ -100,7 +110,7 @@ def handle_request(self):
)
return "Exiting event bus request handler"
except Exception as error:
- self._logger.error(error)
+ self._logger.error(str(error))
return "Error in event bus request handler."
finally:
self._logger.flush()
diff --git a/source/app/instance_scheduler/main.py b/source/app/instance_scheduler/main.py
index fed57935..57dae6e4 100644
--- a/source/app/instance_scheduler/main.py
+++ b/source/app/instance_scheduler/main.py
@@ -1,62 +1,43 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-
import json
-import os
import traceback
-from datetime import datetime
+from datetime import datetime, timezone
from time import time
+from typing import TYPE_CHECKING, Any, Mapping
-from instance_scheduler import configuration
-from instance_scheduler import util
-from instance_scheduler.requesthandlers.admin_cli_request_handler import (
- AdminCliRequestHandler,
-)
-from instance_scheduler.requesthandlers.cloudwatch_event_handler import (
- CloudWatchEventHandler,
-)
-from instance_scheduler.requesthandlers.schedule_resource_handler import (
- ScheduleResourceHandler,
-)
-from instance_scheduler.requesthandlers.scheduler_request_handler import (
- SchedulerRequestHandler,
-)
-from instance_scheduler.requesthandlers.scheduler_setup_handler import (
- SchedulerSetupHandler,
-)
-from instance_scheduler.requesthandlers.eventbus_request_handler import (
- EventBusRequestHandler,
-)
+from instance_scheduler import configuration, util
+from instance_scheduler.handler import handlers
+from instance_scheduler.util.app_env import get_app_env
from instance_scheduler.util.logger import Logger
-from instance_scheduler.version import VERSION
+
+if TYPE_CHECKING:
+ from aws_lambda_powertools.utilities.typing import LambdaContext
+else:
+ LambdaContext = object
LOG_STREAM = "InstanceScheduler-{:0>4d}{:0>2d}{:0>2d}"
-def lambda_handler(event, context):
+def lambda_handler(event: Mapping[str, Any], context: LambdaContext) -> Any:
try:
- dt = datetime.utcnow()
+ dt = datetime.now(timezone.utc)
+ app_env = get_app_env()
log_stream = LOG_STREAM.format(dt.year, dt.month, dt.day)
result = {}
with Logger(
- logstream=log_stream,
- buffersize=20,
- context=context,
- debug=util.as_bool(os.getenv(configuration.ENV_TRACE, False)),
+ log_group=app_env.log_group,
+ log_stream=log_stream,
+ topic_arn=app_env.topic_arn,
+ debug=app_env.enable_debug_logging,
) as logger:
- logger.info("InstanceScheduler, version {}".format(VERSION))
+ logger.info(
+ "InstanceScheduler, version {}".format(app_env.solution_version)
+ )
logger.debug("Event is {}", util.safe_json(event, indent=3))
- for handler_type in [
- SchedulerRequestHandler,
- SchedulerSetupHandler,
- ScheduleResourceHandler,
- AdminCliRequestHandler,
- CloudWatchEventHandler,
- EventBusRequestHandler,
- ]:
+ for handler_type in handlers:
if handler_type.is_handling_request(event):
start = time()
handler = handler_type(event, context)
@@ -79,4 +60,4 @@ def lambda_handler(event, context):
json.dumps(event),
)
finally:
- configuration.unload_scheduler_configuration()
+ configuration.unload_global_configuration()
diff --git a/source/app/instance_scheduler/maint_win/__init__.py b/source/app/instance_scheduler/maint_win/__init__.py
new file mode 100644
index 00000000..6c434e46
--- /dev/null
+++ b/source/app/instance_scheduler/maint_win/__init__.py
@@ -0,0 +1,5 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from .ec2_ssm import EC2SSMMaintenanceWindows
+
+__all__ = ["EC2SSMMaintenanceWindows"]
diff --git a/source/app/instance_scheduler/maint_win/ec2_ssm.py b/source/app/instance_scheduler/maint_win/ec2_ssm.py
new file mode 100644
index 00000000..eab3cc34
--- /dev/null
+++ b/source/app/instance_scheduler/maint_win/ec2_ssm.py
@@ -0,0 +1,330 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from datetime import datetime, timedelta
+from typing import TYPE_CHECKING, Any, Final, Literal
+from zoneinfo import ZoneInfo
+
+import dateutil.parser
+from boto3 import Session
+
+from instance_scheduler.boto_retry import get_client_with_standard_retry
+from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler.configuration.running_period import RunningPeriod
+from instance_scheduler.configuration.running_period_dict_element import (
+ RunningPeriodDictElement,
+)
+from instance_scheduler.configuration.scheduler_config_builder import (
+ SchedulerConfigBuilder,
+)
+from instance_scheduler.model import EC2SSMMaintenanceWindowStore
+from instance_scheduler.util.logger import Logger
+
+if TYPE_CHECKING:
+ from mypy_boto3_ssm.client import SSMClient
+ from mypy_boto3_ssm.type_defs import (
+ DescribeMaintenanceWindowsResultTypeDef,
+ MaintenanceWindowIdentityTypeDef,
+ )
+else:
+ SSMClient = object
+ DescribeMaintenanceWindowsResultTypeDef = object
+ MaintenanceWindowIdentityTypeDef = object
+
+
+class EC2SSMMaintenanceWindows:
+ def __init__(
+ self,
+ *,
+ hub_session: Session,
+ spoke_session: Session,
+ spoke_account_id: str,
+ table_name: str,
+ scheduler_interval: int,
+ logger: Logger,
+ ) -> None:
+ self._spoke_session: Final = spoke_session
+ self._spoke_account_id = spoke_account_id
+ self._scheduler_interval = scheduler_interval
+ self._logger: Final = logger
+
+ self._region: Final = self._spoke_session.region_name
+ self._store: Final = EC2SSMMaintenanceWindowStore(
+ session=hub_session, table_name=table_name, logger=self._logger
+ )
+
+ def get_ssm_windows_service(
+ self, session: Session, region: str
+ ) -> list[MaintenanceWindowIdentityTypeDef]:
+ """
+ This function gets all the ssm windows which are enabled from SSM service.
+
+ Returns:
+ list of ssm windows
+ """
+ ssm_client: SSMClient = get_client_with_standard_retry(
+ "ssm", session=session, region=region
+ )
+ resp_maintenance_windows: DescribeMaintenanceWindowsResultTypeDef = {} # type: ignore
+ try:
+ resp_maintenance_windows = ssm_client.describe_maintenance_windows(
+ Filters=[
+ {
+ "Key": "Enabled",
+ "Values": [
+ "true",
+ ],
+ },
+ ]
+ )
+ except Exception as error:
+ self._logger.error(
+ "Caught Exception while getting the maintenance window: {}".format(
+ error
+ )
+ )
+ ssm_window_list = resp_maintenance_windows.get("WindowIdentities", [])
+ next_token = resp_maintenance_windows.get("NextToken", None)
+ while next_token is not None:
+ try:
+ resp_maintenance_windows = ssm_client.describe_maintenance_windows(
+ Filters=[
+ {
+ "Key": "Enabled",
+ "Values": [
+ "true",
+ ],
+ },
+ ],
+ NextToken=next_token,
+ )
+ except Exception as error:
+ self._logger.error(
+ "Caught Exception while getting the maintenance window: {}".format(
+ error
+ )
+ )
+ next_token = resp_maintenance_windows.get("NextToken", None)
+ ssm_window_list.extend(resp_maintenance_windows.get("WindowIdentities", []))
+ return ssm_window_list
+
+ def process_ssm_window(
+ self,
+ window: MaintenanceWindowIdentityTypeDef,
+ ssm_windows_db: list[Any],
+ account: str,
+ region: str,
+ ) -> MaintenanceWindowIdentityTypeDef:
+ """
+ This function checks if the window is enabled before adding it to the db and update the db for disabled windows.
+
+ Parameters:
+ SSM window object
+ List of maintenance windows from db
+ """
+ new_ssm_window: MaintenanceWindowIdentityTypeDef = {}
+ current_window = {}
+ for window_db in ssm_windows_db:
+ if window_db["Name"] == window["Name"]:
+ current_window = window_db # get the window from the db with the same name as the window from service
+ break
+ if current_window.get("Name") is None:
+ self._store.put_window_dynamodb(
+ window=window, account=account, region=region
+ )
+ new_ssm_window = window
+ else:
+ if not self.check_window_running(current_window):
+ self._store.put_window_dynamodb(
+ window=window, account=account, region=region
+ )
+
+ return new_ssm_window
+
+ def check_window_running(self, window: Any) -> bool:
+ """
+ This function checks if given maintenance window is currently running.
+
+ Parameters:
+ SSM window object
+ """
+ try:
+ duration = window["Duration"]
+ if "ScheduleTimezone" in window:
+ execution_time = datetime.strptime(
+ window["NextExecutionTime"], "%Y-%m-%dT%H:%M%z"
+ )
+ else:
+ execution_time = datetime.strptime(
+ window["NextExecutionTime"], "%Y-%m-%dT%H:%MZ"
+ )
+ window["ScheduleTimezone"] = "UTC"
+
+ tz = ZoneInfo(window["ScheduleTimezone"])
+ window_begin_time = execution_time.replace(tzinfo=tz)
+ window_end_time = execution_time.replace(tzinfo=tz) + timedelta(
+ hours=int(duration)
+ )
+ current_time = datetime.now(tz).replace(tzinfo=tz)
+ return window_begin_time < current_time < window_end_time
+ except Exception as ex:
+ self._logger.error("error in check_window_running {}".format(ex))
+ return False
+
+ def remove_unused_windows(
+ self,
+ *,
+ window_db: Any,
+ ssm_windows_service: list[MaintenanceWindowIdentityTypeDef],
+ ) -> None:
+ """
+ This function removes the old windows not present in the ssm service response.
+ """
+ window_found = False
+ for window_service in ssm_windows_service:
+ if window_service["Name"] == window_db["Name"]:
+ window_found = True
+ break
+ if not window_found:
+ try: # if window from db is not found in the SSM response delete the entry from db
+ self._store.delete_window(window_db)
+ except Exception as error:
+ self._logger.error(
+ "Caught Exception while deleting maintenance windows from Dynamodb: {}".format(
+ error
+ )
+ )
+
+ def get_ssm_windows(self, session: Session, account: str, region: str) -> list[Any]:
+ """
+ This function gets the list of the SSM maintenance windows
+ """
+ new_ssm_windows_list = []
+ ssm_windows_service = self.get_ssm_windows_service(session, region)
+ ssm_windows_db = self._store.get_ssm_windows_db(account=account, region=region)
+ for window_service in ssm_windows_service:
+ new_maintenance_window = self.process_ssm_window(
+ window_service, ssm_windows_db, account, region
+ )
+ if new_maintenance_window:
+ new_ssm_windows_list.append(new_maintenance_window)
+ for window_db in ssm_windows_db:
+ self.remove_unused_windows(
+ window_db=window_db, ssm_windows_service=ssm_windows_service
+ )
+ for window in new_ssm_windows_list:
+ ssm_windows_db.append(window)
+ return ssm_windows_db
+
+ def ssm_maintenance_windows(
+ self, session: Session, account: str, region: str
+ ) -> dict[str, InstanceSchedule | Literal["NOT-FOUND"]]:
+ windows: dict[str, InstanceSchedule | Literal["NOT-FOUND"]] = {}
+ try:
+ window_list = self.get_ssm_windows(session, account, region)
+ for window in window_list:
+ start = dateutil.parser.parse(window["NextExecutionTime"])
+ scheduler_timezone = window.get("ScheduleTimezone", "UTC")
+ maintenance_schedule = self._schedule_from_maint_window(
+ name=window["Name"],
+ start=start,
+ interval=self._scheduler_interval,
+ hours=int(window["Duration"]),
+ timezone=scheduler_timezone,
+ )
+ windows[str(window["Name"])] = maintenance_schedule
+ except Exception as ex:
+ self._logger.error("Error loading ssm maintenace windows, ({})".format(ex))
+
+ return windows
+
+ def _schedule_from_maint_window(
+ self, name: str, start: datetime, hours: int, interval: int, timezone: str
+ ) -> InstanceSchedule:
+ start_dt = start.replace(second=0, microsecond=0)
+ start_before_begin = interval + 10
+ begin_dt = start_dt - timedelta(minutes=start_before_begin)
+ end_dt = start_dt + timedelta(hours=hours)
+ if begin_dt.day == end_dt.day:
+ periods: list[RunningPeriodDictElement] = [
+ {
+ "period": RunningPeriod(
+ name="{}-period".format(name),
+ begintime=begin_dt.time(),
+ endtime=end_dt.time(),
+ monthdays={begin_dt.day},
+ months={begin_dt.month},
+ ),
+ "instancetype": None,
+ }
+ ]
+ elif end_dt - begin_dt <= timedelta(hours=24):
+ periods = [
+ {
+ "period": RunningPeriod(
+ name="{}-period-1".format(name),
+ begintime=begin_dt.time(),
+ endtime=SchedulerConfigBuilder.get_time_from_string("23:59"),
+ monthdays={begin_dt.day},
+ months={begin_dt.month},
+ ),
+ "instancetype": None,
+ },
+ {
+ "period": RunningPeriod(
+ name="{}-period-2".format(name),
+ begintime=SchedulerConfigBuilder.get_time_from_string("00:00"),
+ endtime=end_dt.time(),
+ monthdays={end_dt.day},
+ months={end_dt.month},
+ ),
+ "instancetype": None,
+ },
+ ]
+ else:
+ periods = [
+ {
+ "period": RunningPeriod(
+ name="{}-period-1".format(name),
+ begintime=begin_dt.time(),
+ endtime=SchedulerConfigBuilder.get_time_from_string("23:59"),
+ monthdays={begin_dt.day},
+ months={begin_dt.month},
+ ),
+ "instancetype": None,
+ },
+ {
+ "period": RunningPeriod(
+ name="{}-period-2".format(name),
+ monthdays={(end_dt - timedelta(days=1)).day},
+ months={(end_dt - timedelta(days=1)).month},
+ ),
+ "instancetype": None,
+ },
+ {
+ "period": RunningPeriod(
+ name="{}-period-3".format(name),
+ begintime=SchedulerConfigBuilder.get_time_from_string("00:00"),
+ endtime=end_dt.time(),
+ monthdays={end_dt.day},
+ months={end_dt.month},
+ ),
+ "instancetype": None,
+ },
+ ]
+
+ schedule = InstanceSchedule(
+ name=name,
+ timezone=timezone,
+ description="{} maintenance window".format(name),
+ enforced=True,
+ periods=periods,
+ )
+
+ self._logger.info(
+ "Created schedule {} from SSM maintence window, start is {}, end is {}",
+ name,
+ begin_dt.isoformat(),
+ end_dt.isoformat(),
+ )
+
+ return schedule
diff --git a/source/app/instance_scheduler/model/__init__.py b/source/app/instance_scheduler/model/__init__.py
new file mode 100644
index 00000000..e9570727
--- /dev/null
+++ b/source/app/instance_scheduler/model/__init__.py
@@ -0,0 +1,36 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+"""
+Persistence models and stores for data types used by Instance Scheduler.
+
+Models
+ Model are implemented as dataclasses. They are well-typed representations of the
+ data types stored by Instance scheduler. They are validated on creation and frozen.
+
+ Models implement two static constructors as required: 1/ from the service response
+ describing that data type, and 2/ from the DyanmoDB GetItem response. They also
+ implement a transformation to a `dict[str, AttributeValueTypeDef]` suitable for
+ calls to DynamoDB PutItem, and a transformation to a `dict[str, str]` suitable for
+ calls to DynamoDB DeleteItem.
+
+Stores
+ Stores implement an interface for list, get, put, and delete as needed for a model.
+
+ Stores are backed by Amazon DynamoDB.
+
+Maintenance windows
+ Classes for persistence of representations of EC2 maintenance windows as implemented
+ by AWS Systems Manager.
+
+ Model: `EC2SSMMaintenanceWindow`
+ Raises `EC2SSMMaintenanceWindowValidationError` on validation error
+ Store: `EC2SSMMaintenanceWindowStore`
+"""
+from .maint_win import EC2SSMMaintenanceWindow, EC2SSMMaintenanceWindowValidationError
+from .maint_win_store import EC2SSMMaintenanceWindowStore
+
+__all__ = [
+ "EC2SSMMaintenanceWindow",
+ "EC2SSMMaintenanceWindowStore",
+ "EC2SSMMaintenanceWindowValidationError",
+]
diff --git a/source/app/instance_scheduler/model/maint_win.py b/source/app/instance_scheduler/model/maint_win.py
new file mode 100644
index 00000000..a11a8193
--- /dev/null
+++ b/source/app/instance_scheduler/model/maint_win.py
@@ -0,0 +1,146 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from dataclasses import dataclass
+from datetime import datetime
+from re import fullmatch
+from typing import TYPE_CHECKING, Final
+from zoneinfo import ZoneInfo
+
+from dateutil.parser import isoparse
+
+from instance_scheduler.util.time import is_aware
+
+if TYPE_CHECKING:
+ from mypy_boto3_dynamodb.type_defs import (
+ AttributeValueTypeDef,
+ GetItemOutputTypeDef,
+ )
+ from mypy_boto3_ssm.type_defs import MaintenanceWindowIdentityTypeDef
+else:
+ AttributeValueTypeDef = object
+ GetItemOutputTypeDef = object
+ MaintenanceWindowIdentityTypeDef = object
+
+
+class EC2SSMMaintenanceWindowValidationError(Exception):
+ """An error occurred while validating the consistency of the maintenance window"""
+
+
+@dataclass(frozen=True)
+class EC2SSMMaintenanceWindow:
+ """
+ Model representing a maintenance window for an EC2 instance implemented by AWS SSM.
+
+ Instance Scheduler treats the window name as a unique ID but the service allows
+ multiple windows with the same name to be created.
+
+ Attributes:
+ account_id: 12-digit AWS account ID
+ region: name of the region in which the window is defined
+ window_id: the unique ID of the window as defined by the SSM service
+ window_name: the user-provided name of the window
+ schedule_timezone: the user-provided timezone of the window (default UTC)
+ next_execution_time: the service-calculated next beginning time of the window
+ duration: the duration of the window in hours
+ """
+
+ account_id: str
+ region: str
+ window_id: str
+ window_name: str
+ schedule_timezone: ZoneInfo
+ next_execution_time: datetime
+ duration: int
+
+ def __post_init__(self) -> None:
+ self._validate()
+
+ def _validate(self) -> None:
+ # https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_CreateMaintenanceWindow.html
+ if not fullmatch(r"\d{12}", self.account_id):
+ raise EC2SSMMaintenanceWindowValidationError(
+ f"Invalid account id: {self.account_id}"
+ )
+ if not len(self.region):
+ raise EC2SSMMaintenanceWindowValidationError("Empty region name")
+ if not fullmatch(r"mw-[0-9a-f]{17}", self.window_id):
+ raise EC2SSMMaintenanceWindowValidationError(
+ f"Invalid window ID: {self.window_id}"
+ )
+ if not fullmatch(r"[a-zA-Z0-9_\-.]{3,128}", self.window_name):
+ raise EC2SSMMaintenanceWindowValidationError(
+ f"Invalid maintenance window name: {self.window_name}"
+ )
+ if not is_aware(self.next_execution_time):
+ raise EC2SSMMaintenanceWindowValidationError(
+ f"Non-timezone-aware datetime: {self.next_execution_time}"
+ )
+ if self.duration < 1 or self.duration > 24:
+ raise EC2SSMMaintenanceWindowValidationError(
+ f"Invalid duration: {self.duration}"
+ )
+
+ def to_item(self) -> dict[str, AttributeValueTypeDef]:
+ """Return this object as a dict suitable for a call to DynamoDB `put_item`"""
+ # This definition is consistent with the old behavior, except that
+ # `NextExecutionTime` is encoded using `isoformat`, which produces a stricter
+ # output than the SSM service.
+ return {
+ "account-region": {"S": f"{self.account_id}:{self.region}"},
+ "WindowId": {"S": self.window_id},
+ "Name": {"S": self.window_name},
+ "ScheduleTimezone": {"S": str(self.schedule_timezone)},
+ "NextExecutionTime": {"S": self.next_execution_time.isoformat()},
+ "Duration": {"N": str(self.duration)},
+ }
+
+ def to_key(self) -> dict[str, str]:
+ """Return this object as a key suitable for a call to DynamoDB `delete_item`"""
+ return {
+ "account-region": f"{self.account_id}:{self.region}",
+ "Name": self.window_name,
+ }
+
+ @classmethod
+ def from_identity(
+ cls, *, identity: MaintenanceWindowIdentityTypeDef, account_id: str, region: str
+ ) -> "EC2SSMMaintenanceWindow":
+ """
+ Return a maintenancw window object from an SSM `describe_maintenance_windows`
+ response
+ """
+ # It is critical to use `dateutil.parser.isoparse` to parse `NextExecutionTime`
+ # and not `datetime.datetime.fromisoformat` because `fromisoformat` only
+ # correctly # handles the output of `isoformat`. SSM can output either of the
+ # following, # depending on if the user provided a timezone when creating the
+ # window:
+ # - "2023-06-27T00:00Z"
+ # - "2023-06-27T03:00-04:00"
+ # Both of these are valid ISO 8601 formatted timestamps, but `fromisoformat` can
+ # not parse the zero-UTC-offset timezone shorthand format "Z".
+ return EC2SSMMaintenanceWindow(
+ account_id=account_id,
+ region=region,
+ window_id=identity["WindowId"],
+ window_name=identity["Name"],
+ schedule_timezone=ZoneInfo(identity.get("ScheduleTimezone", "UTC")),
+ next_execution_time=isoparse(identity["NextExecutionTime"]),
+ duration=identity["Duration"],
+ )
+
+ @classmethod
+ def from_item(cls, item: GetItemOutputTypeDef) -> "EC2SSMMaintenanceWindow":
+ """Return a maintenance window object from a DynamoDB `get_item` response"""
+ # Like `from_identity`, this function must use `isoparse` to parse
+ # `next_execution_time` because Instance Scheduler may have stored the value
+ # from the service response verbatim.
+ account_region: Final = item["Item"]["account-region"]["S"].split(":")
+ return EC2SSMMaintenanceWindow(
+ account_id=account_region[0],
+ region=account_region[1],
+ window_id=item["Item"]["WindowId"]["S"],
+ window_name=item["Item"]["Name"]["S"],
+ schedule_timezone=ZoneInfo(item["Item"]["ScheduleTimezone"]["S"]),
+ next_execution_time=isoparse(item["Item"]["NextExecutionTime"]["S"]),
+ duration=int(item["Item"]["Duration"]["N"]),
+ )
diff --git a/source/app/instance_scheduler/model/maint_win_store.py b/source/app/instance_scheduler/model/maint_win_store.py
new file mode 100644
index 00000000..49d0381c
--- /dev/null
+++ b/source/app/instance_scheduler/model/maint_win_store.py
@@ -0,0 +1,118 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from datetime import datetime, timedelta
+from typing import TYPE_CHECKING, Any, Final
+
+from boto3 import Session
+from boto3.dynamodb.conditions import Key
+
+from instance_scheduler.util import get_boto_config
+from instance_scheduler.util.logger import Logger
+
+if TYPE_CHECKING:
+ from mypy_boto3_dynamodb.service_resource import DynamoDBServiceResource, Table
+ from mypy_boto3_dynamodb.type_defs import (
+ ScanInputTableScanTypeDef,
+ ScanOutputTableTypeDef,
+ )
+ from mypy_boto3_ssm.type_defs import MaintenanceWindowIdentityTypeDef
+else:
+ Table = object
+ ScanInputTableScanTypeDef = object
+ ScanOutputTableTypeDef = object
+ MaintenanceWindowIdentityTypeDef = object
+
+
+class EC2SSMMaintenanceWindowStore:
+ def __init__(self, *, session: Session, table_name: str, logger: Logger) -> None:
+ self._logger: Final = logger
+ ddb: Final[DynamoDBServiceResource] = session.resource(
+ "dynamodb", config=get_boto_config()
+ )
+ self._table: Final[Table] = ddb.Table(table_name)
+
+ def get_ssm_windows_db(self, *, account: str, region: str) -> list[Any]:
+ """
+ This function gets all the periods for a given ssm windows from the database.
+ """
+ maintenance_windows: ScanOutputTableTypeDef = {} # type: ignore
+ account_region_string = account + ":" + region
+ try:
+ scan_kwargs: ScanInputTableScanTypeDef = {
+ "FilterExpression": Key("account-region").eq(account_region_string),
+ }
+ maintenance_windows = self._table.scan(**scan_kwargs)
+ except Exception as error:
+ self._logger.error(
+ "Caught Exception while getting maintenance windows from Dynamodb: {}".format(
+ error
+ )
+ )
+ window_list = maintenance_windows.get("Items", [])
+ last_evaluated_key = maintenance_windows.get("LastEvaluatedKey", None)
+ while last_evaluated_key is not None:
+ self._logger.debug(str(maintenance_windows["LastEvaluatedKey"]))
+ try:
+ scan_kwargs = {
+ "FilterExpression": Key("account-region").eq(account_region_string),
+ "ExclusiveStartKey": last_evaluated_key,
+ }
+ maintenance_windows = self._table.scan(**scan_kwargs)
+ except Exception as error:
+ self._logger.error(
+ "Caught Exception while getting maintenance windows from Dynamodb: {}".format(
+ error
+ )
+ )
+ last_evaluated_key = maintenance_windows.get("LastEvaluatedKey", None)
+ window_list.extend(maintenance_windows.get("Items", []))
+ return window_list
+
+ def put_window_dynamodb(
+ self, *, window: MaintenanceWindowIdentityTypeDef, account: str, region: str
+ ) -> None:
+ """
+ This function adds the ssm window entry to the database.
+
+ Parameters:
+ SSM window object
+ """
+ try:
+ duration = window["Duration"]
+ if "ScheduleTimezone" in window:
+ execution_time = datetime.strptime(
+ window["NextExecutionTime"], "%Y-%m-%dT%H:%M%z"
+ )
+ else:
+ execution_time = datetime.strptime(
+ window["NextExecutionTime"], "%Y-%m-%dT%H:%MZ"
+ )
+ window["ScheduleTimezone"] = "UTC"
+
+ ttl = execution_time + timedelta(hours=int(duration))
+ epoch_time_to_live = int(
+ datetime(ttl.year, ttl.month, ttl.day, ttl.hour, ttl.minute).timestamp()
+ )
+ self._table.put_item(
+ Item={
+ "Name": window["Name"],
+ "NextExecutionTime": window["NextExecutionTime"],
+ "Duration": window["Duration"],
+ "WindowId": window["WindowId"],
+ "TimeToLive": epoch_time_to_live,
+ "account-region": account + ":" + region,
+ "ScheduleTimezone": window["ScheduleTimezone"],
+ }
+ )
+ except Exception as error:
+ self._logger.info(
+ "Unable to put maintenance window in Dynamodb: {}".format(error)
+ )
+
+ def delete_window(self, window: Any) -> None:
+ self._table.delete_item(
+ Key={
+ "Name": window["Name"],
+ "account-region": window["account-region"],
+ }
+ )
diff --git a/source/app/instance_scheduler/ops_metrics/__init__.py b/source/app/instance_scheduler/ops_metrics/__init__.py
new file mode 100644
index 00000000..2130add6
--- /dev/null
+++ b/source/app/instance_scheduler/ops_metrics/__init__.py
@@ -0,0 +1,9 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from enum import Enum
+
+
+class GatheringFrequency(str, Enum):
+ UNLIMITED = "UNLIMITED"
+ DAILY = "DAILY"
+ WEEKLY = "WEEKLY"
diff --git a/source/app/instance_scheduler/ops_metrics/anonymous_metric_wrapper.py b/source/app/instance_scheduler/ops_metrics/anonymous_metric_wrapper.py
new file mode 100644
index 00000000..5b76ded0
--- /dev/null
+++ b/source/app/instance_scheduler/ops_metrics/anonymous_metric_wrapper.py
@@ -0,0 +1,15 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from dataclasses import dataclass
+
+from instance_scheduler.ops_metrics.metric_type.ops_metric import OpsMetric
+
+
+@dataclass(frozen=True)
+class AnonymousMetricWrapper:
+ TimeStamp: str
+ UUID: str
+ Solution: str
+ Version: str
+ Event_Name: str
+ Context: OpsMetric
diff --git a/source/app/instance_scheduler/ops_metrics/metric_type/cli_request_metric.py b/source/app/instance_scheduler/ops_metrics/metric_type/cli_request_metric.py
new file mode 100644
index 00000000..bfdc15ca
--- /dev/null
+++ b/source/app/instance_scheduler/ops_metrics/metric_type/cli_request_metric.py
@@ -0,0 +1,14 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from dataclasses import dataclass
+from typing import ClassVar
+
+from instance_scheduler.ops_metrics import GatheringFrequency
+from instance_scheduler.ops_metrics.metric_type.ops_metric import OpsMetric
+
+
+@dataclass(frozen=True)
+class CliRequestMetric(OpsMetric):
+ command_used: str
+ event_name: ClassVar[str] = "cli_request"
+ collection_frequency: ClassVar[GatheringFrequency] = GatheringFrequency.UNLIMITED
diff --git a/source/app/instance_scheduler/ops_metrics/metric_type/configuration_description_metric.py b/source/app/instance_scheduler/ops_metrics/metric_type/configuration_description_metric.py
new file mode 100644
index 00000000..0911fe00
--- /dev/null
+++ b/source/app/instance_scheduler/ops_metrics/metric_type/configuration_description_metric.py
@@ -0,0 +1,38 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from dataclasses import dataclass
+from typing import ClassVar
+
+from instance_scheduler.ops_metrics import GatheringFrequency
+from instance_scheduler.ops_metrics.metric_type.ops_metric import OpsMetric
+
+
+@dataclass()
+class ScheduleFlagCounts:
+ stop_new_instances: int = 0
+ enforced: int = 0
+ retain_running: int = 0
+ hibernate: int = 0
+ override: int = 0
+ use_ssm_maintenance_window: int = 0
+ use_metrics: int = 0
+ non_default_timezone: int = 0
+
+
+@dataclass(frozen=True)
+class ConfigurationDescriptionMetric(OpsMetric):
+ num_schedules: int
+ num_cfn_schedules: int
+ schedule_flag_counts: ScheduleFlagCounts
+ default_timezone: str
+ schedule_aurora_clusters: bool
+ create_rds_snapshots: bool
+ schedule_interval_minutes: int
+ memory_size_mb: int
+ using_organizations: bool
+ enable_ec2_ssm_maintenance_windows: bool
+ num_started_tags: int
+ num_stopped_tags: int
+ event_name: ClassVar[str] = "configuration_description"
+ # collection handler executes once a week, so we do not want any extra filtering
+ collection_frequency: ClassVar[GatheringFrequency] = GatheringFrequency.UNLIMITED
diff --git a/source/app/instance_scheduler/ops_metrics/metric_type/deployment_description_metric.py b/source/app/instance_scheduler/ops_metrics/metric_type/deployment_description_metric.py
new file mode 100644
index 00000000..cbd179f9
--- /dev/null
+++ b/source/app/instance_scheduler/ops_metrics/metric_type/deployment_description_metric.py
@@ -0,0 +1,16 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from dataclasses import dataclass
+from typing import ClassVar
+
+from instance_scheduler.ops_metrics import GatheringFrequency
+from instance_scheduler.ops_metrics.metric_type.ops_metric import OpsMetric
+
+
+@dataclass(frozen=True)
+class DeploymentDescriptionMetric(OpsMetric):
+ services: list[str]
+ regions: list[str]
+ num_accounts: int
+ event_name: ClassVar[str] = "deployment_description"
+ collection_frequency: ClassVar[GatheringFrequency] = GatheringFrequency.DAILY
diff --git a/source/app/instance_scheduler/ops_metrics/metric_type/instance_count_metric.py b/source/app/instance_scheduler/ops_metrics/metric_type/instance_count_metric.py
new file mode 100644
index 00000000..fd553968
--- /dev/null
+++ b/source/app/instance_scheduler/ops_metrics/metric_type/instance_count_metric.py
@@ -0,0 +1,17 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from dataclasses import dataclass
+from typing import ClassVar
+
+from instance_scheduler.ops_metrics import GatheringFrequency
+from instance_scheduler.ops_metrics.metric_type.ops_metric import OpsMetric
+
+
+@dataclass(frozen=True)
+class InstanceCountMetric(OpsMetric):
+ service: str
+ region: str
+ num_instances: int
+ num_schedules: int
+ event_name: ClassVar[str] = "instance_count"
+ collection_frequency: ClassVar[GatheringFrequency] = GatheringFrequency.DAILY
diff --git a/source/app/instance_scheduler/ops_metrics/metric_type/ops_metric.py b/source/app/instance_scheduler/ops_metrics/metric_type/ops_metric.py
new file mode 100644
index 00000000..967080ed
--- /dev/null
+++ b/source/app/instance_scheduler/ops_metrics/metric_type/ops_metric.py
@@ -0,0 +1,13 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from abc import ABC
+from dataclasses import dataclass
+from typing import ClassVar
+
+from instance_scheduler.ops_metrics import GatheringFrequency
+
+
+@dataclass(frozen=True)
+class OpsMetric(ABC):
+ collection_frequency: ClassVar[GatheringFrequency] = GatheringFrequency.UNLIMITED
+ event_name: ClassVar[str]
diff --git a/source/app/instance_scheduler/ops_metrics/metric_type/scheduling_action_metric.py b/source/app/instance_scheduler/ops_metrics/metric_type/scheduling_action_metric.py
new file mode 100644
index 00000000..32be4493
--- /dev/null
+++ b/source/app/instance_scheduler/ops_metrics/metric_type/scheduling_action_metric.py
@@ -0,0 +1,24 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from dataclasses import dataclass
+from typing import ClassVar
+
+from instance_scheduler.ops_metrics import GatheringFrequency
+from instance_scheduler.ops_metrics.metric_type.ops_metric import OpsMetric
+
+
+@dataclass(frozen=True)
+class ActionTaken:
+ instances: int
+ action: str # Literal["started", "stopped", "resized"]
+ service: str # Literal["ec2", "rds"]
+ instanceType: str
+
+
+@dataclass(frozen=True)
+class SchedulingActionMetric(OpsMetric):
+ # todo: add num unique schedules checked
+ duration_seconds: float
+ actions: list[ActionTaken]
+ event_name: ClassVar[str] = "scheduling_action"
+ collection_frequency: ClassVar[GatheringFrequency] = GatheringFrequency.UNLIMITED
diff --git a/source/app/instance_scheduler/ops_metrics/metrics.py b/source/app/instance_scheduler/ops_metrics/metrics.py
new file mode 100644
index 00000000..8a41eec4
--- /dev/null
+++ b/source/app/instance_scheduler/ops_metrics/metrics.py
@@ -0,0 +1,160 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import dataclasses
+import uuid
+from datetime import datetime, timezone
+from typing import TYPE_CHECKING, Optional
+
+import boto3
+import requests
+from botocore.exceptions import ClientError
+from typing_extensions import assert_never
+
+from instance_scheduler.ops_metrics import GatheringFrequency
+from instance_scheduler.ops_metrics.anonymous_metric_wrapper import (
+ AnonymousMetricWrapper,
+)
+from instance_scheduler.ops_metrics.metric_type.ops_metric import OpsMetric
+from instance_scheduler.util import get_boto_config, safe_json
+from instance_scheduler.util.app_env import get_app_env
+from instance_scheduler.util.logger import Logger
+
+if TYPE_CHECKING:
+ from mypy_boto3_ssm.client import SSMClient
+else:
+ SSMClient = object
+
+
+def collect_metric(
+ metric: OpsMetric, logger: Logger
+) -> Optional[AnonymousMetricWrapper]:
+ if not should_collect_metric(metric, logger):
+ return None
+
+ try:
+ app_env = get_app_env()
+ url = app_env.anonymous_metrics_url
+
+ metric_wrapper = AnonymousMetricWrapper(
+ # current required timestamp format for metrics backend (7/11/23)
+ TimeStamp=str(datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S")),
+ UUID=str(_get_deployment_uuid(logger)),
+ Solution=app_env.solution_id,
+ Version=app_env.solution_version,
+ Event_Name=metric.event_name,
+ Context=metric,
+ )
+
+ data_json = safe_json(dataclasses.asdict(metric_wrapper))
+ logger.info("Sending anonymous metrics data: {}", data_json)
+
+ headers = {
+ "content-type": "application/json",
+ "content-length": str(len(data_json)),
+ }
+
+ response = requests.post(url, data=data_json, headers=headers, timeout=300)
+ response.raise_for_status()
+ logger.debug(
+ "Metrics data sent, status code is {}, message is {}",
+ response.status_code,
+ response.text,
+ )
+ return metric_wrapper
+ except Exception as exc:
+ logger.warning(("Failed sending metrics data ({})".format(str(exc))))
+ return None
+
+
+# cache the deployment uuid to try to minimize calls to ssm
+_deployment_uuid: Optional[uuid.UUID] = None
+
+
+def _get_deployment_uuid(logger: Logger) -> uuid.UUID:
+ global _deployment_uuid
+ if not _deployment_uuid:
+ _deployment_uuid = _deployment_uuid_from_ssm(logger)
+ return _deployment_uuid
+
+
+def _deployment_uuid_from_ssm(logger: Logger) -> uuid.UUID:
+ app_env = get_app_env()
+ stack_id = app_env.stack_id[-36:]
+ uuid_key = app_env.uuid_key + str(stack_id)
+ ssm: SSMClient = boto3.client("ssm", config=get_boto_config())
+ try:
+ ssm_response = ssm.get_parameter(Name=uuid_key)
+ uuid_parameter = ssm_response.get("Parameter", {}).get("Value")
+ return uuid.UUID(uuid_parameter)
+ except ClientError as fetch_exception:
+ if fetch_exception.response.get("Error", {}).get("Code") == "ParameterNotFound":
+ uuid_parameter = str(uuid.uuid4())
+ try:
+ logger.info("creating a new parameter")
+ ssm.put_parameter(
+ Name=uuid_key,
+ Description="This is a unique id for each Instance Scheduler on AWS solution stack, for reporting metrics.",
+ Value=uuid_parameter,
+ Type="String",
+ )
+ return uuid.UUID(uuid_parameter)
+ except Exception as create_exception:
+ logger.info(
+ "Unable to create UUID for operational metrics, metrics will not be sent: \n{}".format(
+ create_exception
+ )
+ )
+ raise ValueError("Unable to get solution UUID")
+ else:
+ logger.info(
+ "Unable to fetch UUID for operational metrics, metrics will not be sent: \n{}".format(
+ fetch_exception
+ )
+ )
+ raise ValueError("Unable to get solution UUID")
+
+
+def should_collect_metric(metric: OpsMetric | type[OpsMetric], logger: Logger) -> bool:
+ app_env = get_app_env()
+ if not app_env.send_anonymous_metrics:
+ # do not send metrics when not enabled
+ return False
+
+ try:
+ solution_uuid = _get_deployment_uuid(logger) # can fail
+ interval = app_env.scheduler_frequency_minutes
+ current_time = datetime.now(timezone.utc)
+
+ if metric.collection_frequency is GatheringFrequency.UNLIMITED:
+ return True
+ elif metric.collection_frequency is GatheringFrequency.DAILY:
+ return _is_allowed_hour_for_metrics(
+ solution_uuid, current_time
+ ) and _is_first_call_in_current_hour(current_time, interval)
+ elif metric.collection_frequency is GatheringFrequency.WEEKLY:
+ return (
+ _is_first_day_in_week(current_time)
+ and _is_allowed_hour_for_metrics(solution_uuid, current_time)
+ and _is_first_call_in_current_hour(current_time, interval)
+ )
+ else:
+ assert_never(metric.collection_frequency)
+ except ValueError:
+ return False
+
+
+def _is_first_day_in_week(current_time: datetime) -> bool:
+ return current_time.weekday() == 0
+
+
+def _is_allowed_hour_for_metrics(
+ solution_uuid: uuid.UUID, current_time: datetime
+) -> bool:
+ hour_to_send = solution_uuid.int % 20
+ return current_time.hour == hour_to_send
+
+
+def _is_first_call_in_current_hour(
+ current_time: datetime, scheduling_frequency: int
+) -> bool:
+ return current_time.minute < scheduling_frequency
diff --git a/source/app/instance_scheduler/requesthandlers/cloudwatch_event_handler.py b/source/app/instance_scheduler/requesthandlers/cloudwatch_event_handler.py
deleted file mode 100644
index 5fe5ad93..00000000
--- a/source/app/instance_scheduler/requesthandlers/cloudwatch_event_handler.py
+++ /dev/null
@@ -1,352 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-
-import json
-import os
-from copy import copy
-from datetime import datetime
-
-from instance_scheduler import configuration
-from instance_scheduler.boto_retry import get_client_with_standard_retry
-from instance_scheduler.configuration.scheduler_config_builder import (
- SchedulerConfigBuilder,
-)
-from instance_scheduler.schedulers import SCHEDULER_TYPES
-from instance_scheduler.schedulers.instance_scheduler import InstanceScheduler
-from instance_scheduler.util.logger import Logger
-
-ERR_INVALID_ARN = "{} is not a valid ARN"
-ERR_STARTING_LAMBDA = "Error executing {}, version {} with configuration {}"
-
-INF_CONFIG_TABLE = "Configuration table is {}"
-INF_HANDLER = "Handler {} : Received request {} at {}"
-INF_RUN_SCHEDULER_LOCAL = (
- "Running scheduling request for service(s) {}, account(s) {}, region(s) {}"
-)
-INF_SCHEDULER_RESULT = "Scheduler result is {}"
-INF_STARTING_LAMBDA = (
- "Starting lambda function for scheduling {} instances for account {} in region {}"
-)
-
-LOG_STREAM = "{}-{:0>4d}{:0>2d}{:0>2d}"
-LOG_STREAM_PREFIX = "Scheduler"
-
-WARN_DUPLICATE_ACCOUNT = "Remote account {} is already processed"
-
-
-class CloudWatchEventHandler:
- """
- Handles event from cloudwatch rule time
- """
-
- TOP_LEVEL = 0
- SERVICE_LEVEL = 1
- ACCOUNT_LEVEL = 2
- REGION_LEVEL = 3
-
- def __init__(self, event, context):
- self._context = context
- self._event = event
- self._configuration = None
- self._lambda_client = None
-
- # Setup logging
- classname = self.__class__.__name__
- dt = datetime.utcnow()
- logstream = LOG_STREAM.format(classname, dt.year, dt.month, dt.day)
- self._logger = Logger(logstream=logstream, buffersize=30, context=context)
-
- @property
- def lambda_account(self):
- if "account" in self._event:
- return self._event["account"]
- return os.getenv(configuration.ENV_ACCOUNT)
-
- @property
- def lambda_client(self):
- """
- Get the lambda client
- :return: lambda client
- """
- if self._lambda_client is None:
- self._lambda_client = get_client_with_standard_retry("lambda")
- return self._lambda_client
-
- @property
- def state_table(self):
- """
- Return the name of the state table
- :return: name of the state table
- """
- return os.getenv(configuration.ENV_STATE)
-
- @property
- def configuration(self):
- """
- Returns the scheduler configuration
- :return: scheduler configuration
- """
- if self._configuration is None:
- self._configuration = configuration.get_scheduler_configuration(
- self._logger
- )
- return self._configuration
-
- def account_from_role(self, role_str):
- """
- Extracts the account name from a role arn
- :param role_str: arn of the role
- :return: account from the role, none if it is not a valid role arn
- """
- role_elements = role_str.split(":")
- if len(role_elements) < 5:
- self._logger.error(ERR_INVALID_ARN, role_str)
- return None
- return role_elements[4]
-
- @property
- def accounts_and_roles(self):
- """
- Iterates account and cross-account-roles of the accounts to operate on
- :return:
- """
- processed_accounts = []
-
- if self.configuration.schedule_lambda_account:
- processed_accounts.append(self.lambda_account)
- yield self.lambda_account
-
- for remote_account in self.configuration.remote_account_ids:
- # account = self.account_from_role(role)
- if remote_account is None:
- continue
- # warn and skip if account was already processed
- if remote_account in processed_accounts:
- self._logger.warning(WARN_DUPLICATE_ACCOUNT, remote_account)
- continue
- yield remote_account
-
- def account_names(self, conf):
- """
- Iterates list of accounts to process
- :param conf:
- :return:
- """
- if conf.schedule_lambda_account:
- yield self.lambda_account
-
- for remote_account in conf.remote_account_ids:
- yield remote_account
-
- @staticmethod
- def is_handling_request(event):
- """
- Handler for cloudwatch event to run the scheduler
- :return: True
- """
- return event.get("detail-type", "") == "Scheduled Event"
-
- def _configuration_level_partitions(self, level=TOP_LEVEL):
- def service_level_configs(config):
- for service in config.scheduled_services:
- service_level_config = copy(config)
- service_level_config.scheduled_services = [service]
- yield service_level_config
-
- def account_level_configs(config):
- for service_level_config in service_level_configs(config):
- for account in self.accounts_and_roles:
- account_level_config = copy(service_level_config)
- if account is self.lambda_account:
- account_level_config.schedule_lambda_account = True
- account_level_config.remote_account_ids = []
- else:
- account_level_config.schedule_lambda_account = False
- account_level_config.remote_account_ids = [account]
- yield account_level_config
-
- def region_level_configs(config):
- for account_level_config in account_level_configs(config):
- for region in account_level_config.regions:
- region_level_config = copy(account_level_config)
- region_level_config.regions = [region]
- yield region_level_config
-
- if level == CloudWatchEventHandler.TOP_LEVEL:
- return [self.configuration]
- elif level == CloudWatchEventHandler.SERVICE_LEVEL:
- # noinspection PyTypeChecker
- return list(service_level_configs(self.configuration))
- elif level == CloudWatchEventHandler.ACCOUNT_LEVEL:
- # noinspection PyTypeChecker
- return list(account_level_configs(self.configuration))
- else:
- # noinspection PyTypeChecker
- return list(region_level_configs(self.configuration))
-
- def handle_request(self):
- """
- Handles the CloudWatch Rule timer events
- :return:
- """
-
- def number_of_accounts():
- return (
- len(self.configuration.remote_account_ids) + 1
- if self.configuration.schedule_lambda_account
- else 0
- )
-
- def running_as_lambda():
- return self._context is not None and not self._event.get("no_lambda", False)
-
- def number_of_regions():
- return max(1, len(self.configuration.regions))
-
- def number_of_services():
- return len(self.configuration.scheduled_services)
-
- try:
- self._logger.info(
- INF_HANDLER,
- self.__class__.__name__,
- json.dumps(self._event),
- datetime.now(),
- )
- if running_as_lambda():
- # running as Lambda function
- return self._run_schedulers_as_lambda(
- number_of_accounts, number_of_regions, number_of_services
- )
- else:
- # this is used to run the handler in process from an IDE
- return self._run_schedulers_in_process()
- finally:
- self._logger.flush()
-
- def _run_schedulers_as_lambda(
- self, number_of_accounts, number_of_regions, number_of_services
- ):
- # each service/account/region combination is executed in it's own lambda instance
- level = CloudWatchEventHandler.TOP_LEVEL
- # multiple services, lambda per service
- if number_of_services() > 1:
- level = CloudWatchEventHandler.SERVICE_LEVEL
- # multiple accounts, one lambda per service/account
- if number_of_accounts() > 1:
- level = CloudWatchEventHandler.ACCOUNT_LEVEL
- # multiple regions, one lambda per service/account/region
- if number_of_regions() > 1:
- level = CloudWatchEventHandler.REGION_LEVEL
- result = []
-
- # partition configuration in service/account/region specific subsets and start lambda for each
- for level_configuration in self._configuration_level_partitions(level):
- # noinspection PyTypeChecker
- result.append(self._execute_as_lambda(level_configuration))
- return result
-
- def _run_schedulers_in_process(self):
- # local execution, used for debugging in non lambda environment and IDE's
- result = {}
-
- # noinspection PyTypeChecker
- account_names = list(self.account_names(self.configuration))
- self._logger.info(
- INF_RUN_SCHEDULER_LOCAL.format(
- ", ".join(self.configuration.scheduled_services),
- ", ".join(account_names),
- ", ".join(self.configuration.regions),
- )
- )
-
- for service in self.configuration.scheduled_services:
- service_strategy = SCHEDULER_TYPES[service]()
- scheduler = InstanceScheduler(
- service=service_strategy, scheduler_configuration=self.configuration
- )
- s = "-".join(
- [
- LOG_STREAM_PREFIX,
- "-".join(account_names),
- service,
- "-".join(self.configuration.regions),
- ]
- )
- dt = datetime.utcnow()
- logstream = LOG_STREAM.format(s, dt.year, dt.month, dt.day)
- with Logger(
- logstream=logstream,
- buffersize=60 if self.configuration.trace else 30,
- context=self._context,
- debug=self.configuration.trace,
- ) as logger:
- result[service] = scheduler.run(
- state_table=self.state_table,
- scheduler_config=self.configuration,
- lambda_account=self.lambda_account,
- logger=logger,
- context=self._context,
- )
- self._logger.info(INF_SCHEDULER_RESULT, json.dumps(result, indent=3))
- return result
-
- def _execute_as_lambda(self, conf):
- # runs a service/account/region subset of the configuration as a new lambda function
- self._logger.info(
- INF_STARTING_LAMBDA,
- "-".join(conf.scheduled_services),
- "-".join(self.account_names(conf)),
- "-".join(conf.regions),
- )
-
- # need to convert configuration to dictionary to allow it to be passed in event
- config = SchedulerConfigBuilder.configuration_as_dict(conf)
-
- payload = str.encode(
- json.dumps(
- {
- "action": "scheduler:run",
- "configuration": config,
- "dispatch_time": str(datetime.now()),
- }
- )
- )
-
- if len(payload) > 200000:
- config["schedules"] = {}
- config["periods"] = {}
- payload = str.encode(
- json.dumps(
- {
- "action": "scheduler:run",
- "configuration": config,
- "dispatch_time": str(datetime.now()),
- }
- )
- )
-
- # start the lambda function
- resp = self.lambda_client.invoke(
- FunctionName=self._context.function_name,
- InvocationType="Event",
- LogType="None",
- Payload=payload,
- )
- if resp["StatusCode"] != 202:
- self._logger.error(
- ERR_STARTING_LAMBDA,
- self._context.function_name,
- self._context.function_version,
- config,
- )
-
- result = {
- "services": list(conf.scheduled_services),
- "accounts": list(self.account_names(conf)),
- "regions": list(conf.regions),
- "lambda_invoke_result": resp["StatusCode"],
- "lambda_request_id": resp["ResponseMetadata"]["RequestId"],
- }
- return result
diff --git a/source/app/instance_scheduler/requesthandlers/scheduler_request_handler.py b/source/app/instance_scheduler/requesthandlers/scheduler_request_handler.py
deleted file mode 100644
index 6588e1ee..00000000
--- a/source/app/instance_scheduler/requesthandlers/scheduler_request_handler.py
+++ /dev/null
@@ -1,156 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-
-import os
-from datetime import datetime
-
-from instance_scheduler import configuration
-from instance_scheduler import schedulers
-import pytz
-from instance_scheduler.configuration.scheduler_config_builder import (
- SchedulerConfigBuilder,
-)
-from instance_scheduler.schedulers import SCHEDULER_TYPES
-from instance_scheduler.schedulers.instance_scheduler import InstanceScheduler
-from instance_scheduler.util.logger import Logger
-
-INF_HANDLER = "Handler {} scheduling request for service(s) {}, account(s) {}, region(s) {} at {},\
- time stamp is based on the default timezone selected for the solution."
-INF_SCHEDULER_RESULT = "Scheduler result {}"
-
-LOG_STREAM = "{}-{:0>4d}{:0>2d}{:0>2d}"
-LOG_STREAM_PREFIX = "Scheduler"
-
-
-class SchedulerRequestHandler:
- """
- Class that handled the execution of the scheduler
- """
-
- def __init__(self, event, context):
- self._context = context
- self._event = event
- self._configuration = None
- self._logger = None
-
- @staticmethod
- def is_handling_request(event):
- """
- Tests if this handler handles the event
- :param event: tested event
- :return: True if the handler handles the event
- """
- action = event.get("action", "")
- return action == "scheduler:run"
-
- @property
- def lambda_account(self):
- """
- Returns the name of the lambda account
- :return: lambda account
- """
- if "account" in self._event:
- return self._event["account"]
- return os.getenv(configuration.ENV_ACCOUNT)
-
- @property
- def state_table(self):
- """
- Returns the name of the configuration table
- :return: name of the configuration table
- """
- return os.getenv(configuration.ENV_STATE)
-
- @property
- def configuration(self):
- """
- Gets the configuration passed in the event
- :return: scheduler configuration
- """
- if self._configuration is None:
- # need to reconstruct configuration from dictionary in event
- self._configuration = SchedulerConfigBuilder.configuration_from_dict(
- self._event["configuration"]
- )
- # for large configurations the schedules are not passed in the event, need to reload these here
- if len(self._configuration.schedules) == 0:
- loaded_config = configuration.get_scheduler_configuration(self._logger)
- self._configuration.schedules = loaded_config.schedules
- return self._configuration
-
- @property
- def account_names(self):
- """
- Iterates account names from the configuration
- :return: account names to process
- """
-
- if self.configuration.schedule_lambda_account:
- yield self.lambda_account
-
- for remote_account_id in self.configuration.remote_account_ids:
- yield remote_account_id
-
- def handle_request(self):
- """
- Handles the event
- :return:
- """
- result = {}
-
- account_names = list(self.account_names)
- for service in self.configuration.scheduled_services:
- # gets the implementation that handles the actual scheduling for the service
- service_strategy = SCHEDULER_TYPES[service]()
- # create a scheduler and pass the service strategy
- scheduler = InstanceScheduler(
- service=service_strategy, scheduler_configuration=self.configuration
- )
-
- # setup logging for the service/account/region
- s = "-".join(
- [
- LOG_STREAM_PREFIX,
- service,
- "-".join(account_names),
- "-".join(self.configuration.regions),
- ]
- )
-
- dt = datetime.now(pytz.timezone(self.configuration.default_timezone))
- logstream = LOG_STREAM.format(s, dt.year, dt.month, dt.day)
- self._logger = Logger(
- logstream=logstream,
- buffersize=60 if self.configuration.trace else 30,
- context=self._context,
- debug=self.configuration.trace,
- )
-
- try:
- self._logger.info(
- INF_HANDLER.format(
- self.__class__.__name__,
- ", ".join(self.configuration.scheduled_services),
- ", ".join(list(self.account_names)),
- ", ".join(list(self.configuration.regions)),
- datetime.now(
- pytz.timezone(self.configuration.default_timezone)
- ),
- )
- )
-
- # run the scheduler for the service
- result[service] = scheduler.run(
- state_table=self.state_table,
- scheduler_config=self.configuration,
- lambda_account=self.lambda_account,
- context=self._context,
- logger=self._logger,
- )
- self._logger.info(INF_SCHEDULER_RESULT, result[service])
-
- finally:
- self._logger.flush()
-
- return result
diff --git a/source/app/instance_scheduler/requesthandlers/setup_demo_data.py b/source/app/instance_scheduler/requesthandlers/setup_demo_data.py
deleted file mode 100644
index 22f75e2e..00000000
--- a/source/app/instance_scheduler/requesthandlers/setup_demo_data.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-
-PERIOD_WORKING_DAYS = {
- "name": "working-days",
- "description": "Working days",
- "weekdays": {"mon-fri"},
-}
-PERIOD_WEEKENDS = {
- "name": "weekends",
- "description": "Days in weekend",
- "weekdays": {"sat-sun"},
-}
-PERIOD_OFFICE_HOURS = {
- "name": "office-hours",
- "description": "Office hours",
- "weekdays": {"mon-fri"},
- "begintime": "09:00",
- "endtime": "17:00",
-}
-PERIOD_FIRST_MONDAY_IN_QUARTER = {
- "name": "first-monday-in-quarter",
- "description": "Every first monday of each quarter",
- "weekdays": {"mon#1"},
- "months": "jan/3",
-}
-SCHEDULE_SEATTLE_OFFICE_HOURS = {
- "name": "seattle-office-hours",
- "description": "Office hours in Seattle (Pacific)",
- "periods": {"office-hours"},
- "timezone": "US/Pacific",
-}
-SCHEDULE_UK_OFFICE_HOURS = {
- "name": "uk-office-hours",
- "description": "Office hours in UK",
- "periods": {"office-hours"},
- "timezone": "Europe/London",
-}
-SCHEDULE_STOPPED = {
- "name": "stopped",
- "description": "Instances stopped",
- "override_status": "stopped",
- "use_metrics": False,
-}
-SCHEDULE_RUNNING = {
- "name": "running",
- "description": "Instances running",
- "override_status": "running",
- "use_metrics": False,
-}
-SCHEDULE_SCALING = {
- "name": "scale-up-down",
- "description": "Vertical scaling on weekdays, based on UTC time",
- "periods": {"working-days@t2.micro", "weekends@t2.nano"},
- "timezone": "UTC",
-}
diff --git a/source/app/instance_scheduler/schedulers/__init__.py b/source/app/instance_scheduler/schedulers/__init__.py
index 0b1082bd..04f8b7b7 100644
--- a/source/app/instance_scheduler/schedulers/__init__.py
+++ b/source/app/instance_scheduler/schedulers/__init__.py
@@ -1,55 +1,2 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-
-from instance_scheduler.schedulers.ec2_service import Ec2Service
-from instance_scheduler.schedulers.rds_service import RdsService
-
-INST_ALLOW_RESIZE = "allow_resize"
-INST_RESIZED = "resized"
-INST_ARN = "arn"
-INST_CURRENT_STATE = "current_state"
-INST_ID = "id"
-INST_INSTANCE_TYPE = "instancetype"
-INST_IS_RUNNING = "is_running"
-INST_IS_TERMINATED = "is_terminated"
-INST_MULTI_AZ = "multi_az"
-INST_NAME = "name"
-INST_SCHEDULE = "schedule_name"
-INST_HIBERNATE = "hibernate"
-INST_STATE = "state"
-INST_STATE_NAME = "state_name"
-INST_TAGS = "tags"
-INST_MAINTENANCE_WINDOW = "maintenance_window"
-INST_ENGINE_TYPE = "engine_type"
-INST_DB_ARN = "db_inst_arn"
-INST_DB_IS_CLUSTER = "is_cluster"
-
-PARAM_ACCOUNT = "account"
-PARAM_CONTEXT = "context"
-PARAM_DESIRED_TYPE = "desired_type"
-PARAM_INSTANCE = "instance"
-PARAM_LOGGER = "logger"
-PARAM_REGION = "region"
-PARAM_ROLE = "role"
-PARAM_SESSION = "session"
-PARAM_STARTED_INSTANCES = "started_instances"
-PARAM_STOPPED_INSTANCES = "stopped_instances"
-PARAM_TAG_NAME = "tagname"
-PARAM_TRACE = "trace"
-PARAM_STACK = "stack_name"
-PARAM_CONFIG = "configuration"
-PARAM_CLUSTERS = "clusters"
-
-
-# Services handled by the scheduler, the class that handles the logic for scheduling instances for each know service
-# must be registered here
-
-SCHEDULER_TYPES = {"ec2": Ec2Service, "rds": RdsService}
-
-
-def account_from_role(role_str):
- role_elements = role_str.split(":")
- if len(role_elements) < 5:
- return ""
- return role_elements[4]
diff --git a/source/app/instance_scheduler/schedulers/ec2_service.py b/source/app/instance_scheduler/schedulers/ec2_service.py
deleted file mode 100644
index 605481fb..00000000
--- a/source/app/instance_scheduler/schedulers/ec2_service.py
+++ /dev/null
@@ -1,867 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-
-import os
-import boto3
-from datetime import timedelta, datetime
-import dateutil
-import jmespath
-import pytz
-from botocore.exceptions import ClientError
-
-from instance_scheduler import configuration
-from instance_scheduler import schedulers
-import time
-from instance_scheduler.boto_retry import get_client_with_standard_retry
-from instance_scheduler.configuration import SchedulerConfigBuilder
-from instance_scheduler.configuration.instance_schedule import InstanceSchedule
-from instance_scheduler.configuration.running_period import RunningPeriod
-from boto3.dynamodb.conditions import Key
-
-# instances are started in batches, larger bathes are more efficient but smaller batches allow more instances
-# to start if we run into resource limits
-
-ERR_RESIZING_INSTANCE_ = "Error resizing instance {}, ({})"
-
-START_BATCH_SIZE = 5
-STOP_BATCH_SIZE = 50
-
-ERR_STARTING_INSTANCES = "Error starting instances {}, ({})"
-ERR_STOPPING_INSTANCES = "Error stopping instances {}, ({})"
-ERR_MAINT_WINDOW_NOT_FOUND_OR_DISABLED = (
- "SSM maintenance window {} used in schedule {} not found or disabled"
-)
-
-INF_FETCHED_INSTANCES = "Number of fetched ec2 instances is {}, number of instances in a schedulable state is {}"
-INF_FETCHING_INSTANCES = "Fetching ec2 instances for account {} in region {}"
-INF_SETTING_SIZE = "Setting size for ec2 instance {} to {}"
-INF_ADD_KEYS = "Adding {} key(s) {} to instance(s) {}"
-INFO_REMOVING_KEYS = "Removing {} key(s) {} from instance(s) {}"
-INF_MAINT_WINDOW = (
- "Created schedule {} from SSM maintence window, start is {}, end is {}"
-)
-INF_MAINT_WINDOW_DISABLED = "SSM maintenance window {} ({}) is disabled"
-
-WARN_STARTED_INSTANCES_TAGGING = (
- "Error deleting or creating tags for started instances {} ({})"
-)
-WARN_STOPPED_INSTANCES_TAGGING = (
- "Error deleting or creating tags for stopped instances {} ({})"
-)
-WARNING_INSTANCE_NOT_STARTING = "Ec2 instance {} is not started"
-WARNING_INSTANCE_NOT_STOPPING = "Ec2 instance {} is not stopped"
-WARN_NOT_HIBERNATED = (
- "Instance {} could not be hibernated, retry to stop without hibernation, {}"
-)
-WARN_NO_HIBERNATE_RESIZED = (
- "Instance {} is not hibernated because it is stopped for resizing the instance"
-)
-
-DEBUG_SKIPPED_INSTANCE = (
- "Skipping ec2 instance {} because it it not in a schedulable state ({})"
-)
-DEBUG_SELECTED_INSTANCE = "Selected ec2 instance {} in state ({})"
-
-
-class Ec2Service:
- """
- Implements service start/stop/resize functions for EC2 service
- """
-
- EC2_STATE_PENDING = 0
- EC2_STATE_RUNNING = 16
- EC2_STATE_SHUTTING_DOWN = 32
- EC2_STATE_TERMINATED = 48
- EC2_STATE_STOPPING = 64
- EC2_STATE_STOPPED = 80
-
- EC2_SCHEDULABLE_STATES = {EC2_STATE_RUNNING, EC2_STATE_STOPPED}
- EC2_STOPPING_STATES = {
- EC2_STATE_SHUTTING_DOWN,
- EC2_STATE_STOPPING,
- EC2_STATE_STOPPED,
- }
- EC2_STARTING_STATES = {EC2_STATE_PENDING, EC2_STATE_RUNNING}
-
- def __init__(self):
- self.service_name = "ec2"
- self.allow_resize = True
- self.schedules_with_hibernation = []
- self._ssm_maintenance_windows = None
- self._session = None
- self._logger = None
- self._dynamodb = boto3.resource("dynamodb")
- self._maintenance_table = self._dynamodb.Table(
- os.environ["MAINTENANCE_WINDOW_TABLE"]
- )
-
- def _init_scheduler(self, args):
- self._session = args.get(schedulers.PARAM_SESSION)
- self._context = args.get(schedulers.PARAM_CONTEXT)
- self._region = args.get(schedulers.PARAM_REGION)
- self._logger = args.get(schedulers.PARAM_LOGGER)
- self._account = args.get(schedulers.PARAM_ACCOUNT)
- self._tagname = args.get(schedulers.PARAM_TAG_NAME)
-
- @classmethod
- def instance_batches(cls, instances, size):
- instance_buffer = []
- for instance in instances:
- instance_buffer.append(instance)
- if len(instance_buffer) == size:
- yield instance_buffer
- instance_buffer = []
- if len(instance_buffer) > 0:
- yield instance_buffer
-
- def get_ssm_windows_service(self, session, region):
- """
- This function gets all the ssm windows which are enabled from SSM service.
-
- Returns:
- list of ssm windows
- """
- ssm_client = get_client_with_standard_retry(
- "ssm", session=session, region=region
- )
- resp_maintenance_windows = {}
- try:
- resp_maintenance_windows = ssm_client.describe_maintenance_windows(
- Filters=[
- {
- "Key": "Enabled",
- "Values": [
- "true",
- ],
- },
- ]
- )
- except Exception as error:
- self._logger.error(
- "Caught Exception while getting the maintenance window: {}".format(
- error
- )
- )
- ssm_window_list = resp_maintenance_windows.get("WindowIdentities", [])
- next_token = resp_maintenance_windows.get("NextToken", None)
- while next_token is not None:
- try:
- resp_maintenance_windows = ssm_client.describe_maintenance_windows(
- Filters=[
- {
- "Key": "Enabled",
- "Values": [
- "true",
- ],
- },
- ],
- NextToken=next_token,
- )
- except Exception as error:
- self._logger.error(
- "Caught Exception while getting the maintenance window: {}".format(
- error
- )
- )
- next_token = resp_maintenance_windows.get("NextToken", None)
- ssm_window_list.extend(resp_maintenance_windows.get("WindowIdentities", []))
- return ssm_window_list
-
- def get_ssm_windows_db(self, account, region):
- """
- This function gets all the periods for a given ssm windows from the database.
- """
- maintenance_windows = {}
- accountRegionString = account + ":" + region
- try:
- scan_kwargs = {
- "FilterExpression": Key("account-region").eq(accountRegionString),
- }
- maintenance_windows = self._maintenance_table.scan(**scan_kwargs)
- except Exception as error:
- self._logger.error(
- "Caught Exception while getting maintenance windows from Dynamodb: {}".format(
- error
- )
- )
- window_list = maintenance_windows.get("Items", [])
- last_evaluated_key = maintenance_windows.get("LastEvaluatedKey", None)
- while last_evaluated_key is not None:
- self._logger.debug(maintenance_windows["LastEvaluatedKey"])
- try:
- scan_kwargs = {
- "FilterExpression": Key("account-region").eq(accountRegionString),
- "ExclusiveStartKey": last_evaluated_key,
- }
- maintenance_windows = self._maintenance_table.scan(**scan_kwargs)
- except Exception as error:
- self._logger.error(
- "Caught Exception while getting maintenance windows from Dynamodb: {}".format(
- error
- )
- )
- last_evaluated_key = maintenance_windows.get("LastEvaluatedKey", None)
- window_list.extend(maintenance_windows.get("Items", []))
- return window_list
-
- def process_ssm_window(self, window, ssm_windows_db, account, region):
- """
- This function checks if the window is enabled before adding it to the db and update the db for disabled windows.
-
- Parameters:
- SSM window object
- List of maintenance windows from db
- """
- new_ssm_window = {}
- current_window = {}
- for window_db in ssm_windows_db:
- if window_db["Name"] == window["Name"]:
- current_window = window_db # get the window from the db with the same name as the window from service
- break
- if current_window.get("Name") is None:
- self.put_window_dynamodb(window, account, region)
- new_ssm_window = window
- else:
- if not self.check_window_running(current_window):
- self.put_window_dynamodb(window, account, region)
-
- return new_ssm_window
-
- def check_window_running(self, window):
- """
- This function checks if given maintenance window is currently running.
-
- Parameters:
- SSM window object
- """
- try:
- duration = window["Duration"]
- if "ScheduleTimezone" in window:
- execution_time = datetime.strptime(
- window["NextExecutionTime"], "%Y-%m-%dT%H:%M%z"
- )
- else:
- execution_time = datetime.strptime(
- window["NextExecutionTime"], "%Y-%m-%dT%H:%MZ"
- )
- window["ScheduleTimezone"] = "UTC"
-
- tz = pytz.timezone(window["ScheduleTimezone"])
- window_begin_time = execution_time.replace(tzinfo=tz)
- window_end_time = execution_time.replace(tzinfo=tz) + timedelta(
- hours=int(duration)
- )
- current_time = datetime.now(tz).replace(tzinfo=tz)
- return window_begin_time < current_time < window_end_time
- except Exception as ex:
- self._logger.error("error in check_window_running {}".format(ex))
- return False
-
- def put_window_dynamodb(self, window, account, region):
- """
- This function adds the ssm window entry to the database.
-
- Parameters:
- SSM window object
- """
- try:
- duration = window["Duration"]
- if "ScheduleTimezone" in window:
- execution_time = datetime.strptime(
- window["NextExecutionTime"], "%Y-%m-%dT%H:%M%z"
- )
- else:
- execution_time = datetime.strptime(
- window["NextExecutionTime"], "%Y-%m-%dT%H:%MZ"
- )
- window["ScheduleTimezone"] = "UTC"
-
- ttl = execution_time + timedelta(hours=int(duration))
- epoch_time_to_live = int(
- datetime(ttl.year, ttl.month, ttl.day, ttl.hour, ttl.minute).timestamp()
- )
- self._maintenance_table.put_item(
- Item={
- "Name": window["Name"],
- "NextExecutionTime": window["NextExecutionTime"],
- "Duration": window["Duration"],
- "WindowId": window["WindowId"],
- "TimeToLive": epoch_time_to_live,
- "account-region": account + ":" + region,
- "ScheduleTimezone": window["ScheduleTimezone"],
- }
- )
- except Exception as error:
- self._logger.info(
- "Unable to put maintenance window in Dynamodb: {}".format(error)
- )
-
- def remove_unused_windows(self, window_db, ssm_windows_service):
- """
- This function removes the old windows not present in the ssm service response.
- """
- window_found = False
- for window_service in ssm_windows_service:
- if window_service["Name"] == window_db["Name"]:
- window_found = True
- break
- if not window_found:
- try: # if window from db is not found in the SSM response delete the entry from db
- self._maintenance_table.delete_item(
- Key={
- "Name": window_db["Name"],
- "account-region": window_db["account-region"],
- }
- )
- except Exception as error:
- self._logger.error(
- "Caught Exception while deleting maintenance windows from Dynamodb: {}".format(
- error
- )
- )
-
- def get_ssm_windows(self, session, context, account, region):
- """
- This function gets the list of the SSM maintenance windows
- """
- new_ssm_windows_list = []
- ssm_windows_service = self.get_ssm_windows_service(session, region)
- ssm_windows_db = self.get_ssm_windows_db(account, region)
- for window_service in ssm_windows_service:
- new_maintenance_window = self.process_ssm_window(
- window_service, ssm_windows_db, account, region
- )
- if new_maintenance_window:
- new_ssm_windows_list.append(new_maintenance_window)
- for window_db in ssm_windows_db:
- self.remove_unused_windows(window_db, ssm_windows_service)
- for window in new_ssm_windows_list:
- ssm_windows_db.append(window)
- return ssm_windows_db
-
- def ssm_maintenance_windows(self, session, context, account, region):
- if self._ssm_maintenance_windows is None:
- self._ssm_maintenance_windows = {}
- try:
- window_list = self.get_ssm_windows(session, context, account, region)
- for window in window_list:
- start = dateutil.parser.parse(window["NextExecutionTime"])
- scheduler_timezone = window.get("ScheduleTimezone", "UTC")
- scheduler_interval = max(
- 10, int(os.getenv(configuration.ENV_SCHEDULE_FREQUENCY))
- )
- maintenance_schedule = self._schedule_from_maint_window(
- name=window["Name"],
- start=start,
- interval=scheduler_interval,
- hours=int(window["Duration"]),
- timezone=scheduler_timezone,
- )
- self._ssm_maintenance_windows[window["Name"]] = maintenance_schedule
- except Exception as ex:
- self._logger.error(
- "Error loading ssm maintenace windows, ({})".format(ex)
- )
-
- return self._ssm_maintenance_windows
-
- # get instances and handle paging
- def get_schedulable_instances(self, kwargs):
- self._session = kwargs[schedulers.PARAM_SESSION]
- context = kwargs[schedulers.PARAM_CONTEXT]
- region = kwargs[schedulers.PARAM_REGION]
- account = kwargs[schedulers.PARAM_ACCOUNT]
- self._logger = kwargs[schedulers.PARAM_LOGGER]
- tagname = kwargs[schedulers.PARAM_CONFIG].tag_name
- config = kwargs[schedulers.PARAM_CONFIG]
-
- self.schedules_with_hibernation = [
- s.name for s in config.schedules.values() if s.hibernate
- ]
-
- self._logger.info(
- "Enable SSM Maintenance window is set to {}",
- config.enable_SSM_maintenance_windows,
- )
- if config.enable_SSM_maintenance_windows:
- # calling the get maintenance window for this account and region.
- self._logger.debug(
- "load the ssm maintenance windows for account {}, and region {}",
- account,
- region,
- )
- self._ssm_maintenance_windows = self.ssm_maintenance_windows(
- self._session, context, account, region
- )
- self._logger.debug("finish loading the ssm maintenance windows")
-
- client = get_client_with_standard_retry(
- "ec2", session=self._session, region=region
- )
-
- def is_in_schedulable_state(ec2_inst):
- state = ec2_inst["state"] & 0xFF
- return state in Ec2Service.EC2_SCHEDULABLE_STATES
-
- jmes = (
- "Reservations[*].Instances[*].{InstanceId:InstanceId, EbsOptimized:EbsOptimized, Tags:Tags, "
- "InstanceType:InstanceType,State:State}[]"
- + "|[?Tags]|[?contains(Tags[*].Key, '{}')]".format(tagname)
- )
-
- args = {}
- number_of_instances = 0
- instances = []
- done = False
-
- self._logger.info(INF_FETCHING_INSTANCES, account, region)
-
- while not done:
- ec2_resp = client.describe_instances(**args)
- for reservation_inst in jmespath.search(jmes, ec2_resp):
- inst = self._select_instance_data(
- instance=reservation_inst, tagname=tagname, config=config
- )
- number_of_instances += 1
- if is_in_schedulable_state(inst):
- instances.append(inst)
- self._logger.debug(
- DEBUG_SELECTED_INSTANCE,
- inst[schedulers.INST_ID],
- inst[schedulers.INST_STATE_NAME],
- )
- else:
- self._logger.debug(
- DEBUG_SKIPPED_INSTANCE,
- inst[schedulers.INST_ID],
- inst[schedulers.INST_STATE_NAME],
- )
- if "NextToken" in ec2_resp:
- args["NextToken"] = ec2_resp["NextToken"]
- else:
- done = True
- self._logger.info(INF_FETCHED_INSTANCES, number_of_instances, len(instances))
- return instances
-
- def _schedule_from_maint_window(self, name, start, hours, interval, timezone):
- start_dt = start.replace(second=0, microsecond=0)
- start_before_begin = max(interval, 10)
- begin_dt = start_dt - timedelta(minutes=start_before_begin)
- end_dt = start_dt + timedelta(hours=hours)
- if begin_dt.day == end_dt.day:
- periods = [
- {
- "period": RunningPeriod(
- name="{}-period".format(name),
- begintime=begin_dt.time(),
- endtime=end_dt.time(),
- monthdays={begin_dt.day},
- months={begin_dt.month},
- ),
- "instancetype": None,
- }
- ]
- elif end_dt - begin_dt <= timedelta(hours=24):
- periods = [
- {
- "period": RunningPeriod(
- name="{}-period-1".format(name),
- begintime=begin_dt.time(),
- endtime=SchedulerConfigBuilder.get_time_from_string("23:59"),
- monthdays={begin_dt.day},
- months={begin_dt.month},
- ),
- "instancetype": None,
- },
- {
- "period": RunningPeriod(
- name="{}-period-2".format(name),
- begintime=SchedulerConfigBuilder.get_time_from_string("00:00"),
- endtime=end_dt.time(),
- monthdays={end_dt.day},
- months={end_dt.month},
- ),
- "instancetype": None,
- },
- ]
- else:
- periods = [
- {
- "period": RunningPeriod(
- name="{}-period-1".format(name),
- begintime=begin_dt.time(),
- endtime=SchedulerConfigBuilder.get_time_from_string("23:59"),
- monthdays={begin_dt.day},
- months={begin_dt.month},
- ),
- "instancetype": None,
- },
- {
- "period": RunningPeriod(
- name="{}-period-2".format(name),
- monthdays={(end_dt - timedelta(days=1)).day},
- months={(end_dt - timedelta(days=1)).month},
- ),
- "instancetype": None,
- },
- {
- "period": RunningPeriod(
- name="{}-period-3".format(name),
- begintime=SchedulerConfigBuilder.get_time_from_string("00:00"),
- endtime=end_dt.time(),
- monthdays={end_dt.day},
- months={end_dt.month},
- ),
- "instancetype": None,
- },
- ]
-
- schedule = InstanceSchedule(
- name=name,
- timezone=timezone,
- description="{} maintenance window".format(name),
- enforced=True,
- periods=periods,
- )
-
- self._logger.info(
- INF_MAINT_WINDOW, name, begin_dt.isoformat(), end_dt.isoformat()
- )
-
- return schedule
-
- # selects and builds a named tuple for the instance data
- def _select_instance_data(self, instance, tagname, config):
- def get_tags(inst):
- return (
- {tag["Key"]: tag["Value"] for tag in inst["Tags"]}
- if "Tags" in inst
- else {}
- )
-
- tags = get_tags(instance)
- name = tags.get("Name", "")
- instance_id = instance["InstanceId"]
- state = instance["State"]["Code"] & 0xFF
- is_running = self.EC2_STATE_RUNNING == state
- is_terminated = state == Ec2Service.EC2_STATE_TERMINATED
- schedule_name = tags.get(tagname)
-
- maintenance_window_schedule = None
- schedule = config.schedules.get(schedule_name, None)
- if schedule is not None:
- if (
- schedule.use_maintenance_window
- and schedule.ssm_maintenance_window not in [None, ""]
- ):
- maintenance_window_schedule = self._ssm_maintenance_windows.get(
- schedule.ssm_maintenance_window, None
- )
- if maintenance_window_schedule is None:
- self._logger.error(
- ERR_MAINT_WINDOW_NOT_FOUND_OR_DISABLED,
- schedule.ssm_maintenance_window,
- schedule.name,
- )
- self._ssm_maintenance_windows[
- schedule.ssm_maintenance_window
- ] = "NOT-FOUND"
- if maintenance_window_schedule == "NOT-FOUND":
- maintenance_window_schedule = None
-
- instance_data = {
- schedulers.INST_ID: instance_id,
- schedulers.INST_SCHEDULE: schedule_name,
- schedulers.INST_HIBERNATE: schedule_name in self.schedules_with_hibernation,
- schedulers.INST_NAME: name,
- schedulers.INST_STATE: state,
- schedulers.INST_STATE_NAME: instance["State"]["Name"],
- schedulers.INST_ALLOW_RESIZE: self.allow_resize,
- schedulers.INST_RESIZED: False,
- schedulers.INST_IS_RUNNING: is_running,
- schedulers.INST_IS_TERMINATED: is_terminated,
- schedulers.INST_CURRENT_STATE: InstanceSchedule.STATE_RUNNING
- if is_running
- else InstanceSchedule.STATE_STOPPED,
- schedulers.INST_INSTANCE_TYPE: instance["InstanceType"],
- schedulers.INST_TAGS: tags,
- schedulers.INST_MAINTENANCE_WINDOW: maintenance_window_schedule,
- }
- return instance_data
-
- # noinspection PyMethodMayBeStatic
- def resize_instance(self, kwargs):
- self._init_scheduler(kwargs)
- instance = kwargs[schedulers.PARAM_INSTANCE]
- instance_type = kwargs[schedulers.PARAM_DESIRED_TYPE]
-
- client = get_client_with_standard_retry(
- "ec2", session=self._session, region=self._region
- )
-
- self._logger.info(INF_SETTING_SIZE, instance.id, instance_type)
-
- try:
- client.modify_instance_attribute(
- InstanceId=instance.id, InstanceType={"Value": instance_type}
- )
- except Exception as ex:
- self._logger.error(ERR_RESIZING_INSTANCE_, ",".join(instance.id), str(ex))
-
- # noinspection PyMethodMayBeStatic
- def get_instance_status(self, client, instance_ids):
- status_resp = client.describe_instances(InstanceIds=instance_ids)
- jmes = "Reservations[*].Instances[*].{InstanceId:InstanceId, State:State}[]"
- return jmespath.search(jmes, status_resp)
-
- # noinspection PyMethodMayBeStatic
- def stop_instances(self, kwargs):
- def is_in_stopping_state(state):
- return (state & 0xFF) in Ec2Service.EC2_STOPPING_STATES
-
- self._init_scheduler(kwargs)
-
- stopped_instances = kwargs[schedulers.PARAM_STOPPED_INSTANCES]
- stop_tags = kwargs[schedulers.PARAM_CONFIG].stopped_tags
- if stop_tags is None:
- stop_tags = []
- stop_tags_key_names = [t["Key"] for t in stop_tags]
-
- start_tags_keys = [
- {"Key": t["Key"]}
- for t in kwargs[schedulers.PARAM_CONFIG].started_tags
- if t["Key"] not in stop_tags_key_names
- ]
-
- methods = ["stop_instances", "create_tags", "delete_tags", "describe_instances"]
- client = get_client_with_standard_retry(
- "ec2", session=self._session, region=self._region
- )
-
- for instance_batch in list(
- self.instance_batches(stopped_instances, STOP_BATCH_SIZE)
- ):
- instance_ids = [i.id for i in instance_batch]
-
- # split in hibernated and non hibernated, instanced that are stopped for resizing cannot be hibernated
- hibernated = [i.id for i in instance_batch if i.hibernate and not i.resized]
- not_hibernated = [i.id for i in instance_batch if i.id not in hibernated]
-
- for inst in [i for i in instance_batch if i.hibernate and i.resized]:
- self._logger.warning(WARN_NO_HIBERNATE_RESIZED, inst.id)
-
- instances_stopping = []
-
- try:
- while len(hibernated) > 0:
- try:
- stop_resp = client.stop_instances(
- InstanceIds=hibernated, Hibernate=True
- )
- instances_stopping += [
- i["InstanceId"]
- for i in stop_resp.get("StoppingInstances", [])
- if is_in_stopping_state(
- i.get("CurrentState", {}).get("Code", "")
- )
- ]
- break
- except ClientError as ex:
- instance_id = None
- if (
- ex.response.get("Error", {}).get("Code")
- == "UnsupportedHibernationConfiguration"
- ):
- instance_id = (
- ex.response["Error"]["Message"].split(":")[-1].strip()
- )
- elif (
- ex.response.get("Error", {}).get("Code")
- == "UnsupportedOperation"
- ):
- instance_id = (
- ex.response["Error"]["Message"].split(" ")[1].strip()
- )
- if instance_id in hibernated:
- self._logger.warning(WARN_NOT_HIBERNATED, instance_id, ex)
- hibernated.remove(instance_id)
- not_hibernated.append(instance_id)
- else:
- self._logger.error(
- ERR_STOPPING_INSTANCES, ",".join(hibernated), str(ex)
- )
-
- if len(not_hibernated) > 0:
- try:
- stop_resp = client.stop_instances(
- InstanceIds=not_hibernated, Hibernate=False
- )
- instances_stopping += [
- i["InstanceId"]
- for i in stop_resp.get("StoppingInstances", [])
- if is_in_stopping_state(
- i.get("CurrentState", {}).get("Code", "")
- )
- ]
- except Exception as ex:
- self._logger.error(
- ERR_STOPPING_INSTANCES, ",".join(not_hibernated), str(ex)
- )
-
- get_status_count = 0
- if len(instances_stopping) < len(instance_ids):
- time.sleep(5)
-
- instances_stopping = [
- i["InstanceId"]
- for i in self.get_instance_status(client, instance_ids)
- if is_in_stopping_state(i.get("State", {}).get("Code", ""))
- ]
-
- if len(instances_stopping) == len(instance_ids):
- break
-
- get_status_count += 1
- if get_status_count > 3:
- for i in instance_ids:
- if i not in instances_stopping:
- self._logger.warning(WARNING_INSTANCE_NOT_STOPPING, i)
- break
-
- if len(instances_stopping) > 0:
- try:
- if start_tags_keys is not None and len(start_tags_keys):
- self._logger.info(
- INFO_REMOVING_KEYS,
- "start",
- ",".join(
- ['"{}"'.format(k["Key"]) for k in start_tags_keys]
- ),
- ",".join(instances_stopping),
- )
- client.delete_tags(
- Resources=instances_stopping, Tags=start_tags_keys
- )
- if len(stop_tags) > 0:
- self._logger.info(
- INF_ADD_KEYS,
- "stop",
- str(stop_tags),
- ",".join(instances_stopping),
- )
- client.create_tags(
- Resources=instances_stopping, Tags=stop_tags
- )
- except Exception as ex:
- self._logger.warning(
- WARN_STOPPED_INSTANCES_TAGGING,
- ",".join(instances_stopping),
- str(ex),
- )
-
- for i in instances_stopping:
- yield i, InstanceSchedule.STATE_STOPPED
-
- except Exception as ex:
- self._logger.error(
- ERR_STOPPING_INSTANCES, ",".join(instance_ids), str(ex)
- )
-
- # noinspection PyMethodMayBeStatic
- def start_instances(self, kwargs):
- def is_in_starting_state(state):
- return (state & 0xFF) in Ec2Service.EC2_STARTING_STATES
-
- self._init_scheduler(kwargs)
-
- instances_to_start = kwargs[schedulers.PARAM_STARTED_INSTANCES]
- start_tags = kwargs[schedulers.PARAM_CONFIG].started_tags
- if start_tags is None:
- start_tags = []
- start_tags_key_names = [t["Key"] for t in start_tags]
- stop_tags_keys = [
- {"Key": t["Key"]}
- for t in kwargs[schedulers.PARAM_CONFIG].stopped_tags
- if t["Key"] not in start_tags_key_names
- ]
- client = get_client_with_standard_retry(
- "ec2", session=self._session, region=self._region
- )
-
- if os.environ["START_EC2_BATCH_SIZE"] is not None:
- try:
- START_BATCH_SIZE = int(os.environ["START_EC2_BATCH_SIZE"])
- except Exception as ex:
- self._logger.info(ex)
-
- for instance_batch in self.instance_batches(
- instances_to_start, START_BATCH_SIZE
- ):
- instance_ids = [i.id for i in list(instance_batch)]
- try:
- start_resp = client.start_instances(InstanceIds=instance_ids)
- instances_starting = [
- i["InstanceId"]
- for i in start_resp.get("StartingInstances", [])
- if is_in_starting_state(i.get("CurrentState", {}).get("Code", ""))
- ]
-
- get_status_count = 0
- if len(instances_starting) < len(instance_ids):
- time.sleep(5)
-
- instances_starting = [
- i["InstanceId"]
- for i in self.get_instance_status(client, instance_ids)
- if is_in_starting_state(i.get("State", {}).get("Code", ""))
- ]
-
- if len(instances_starting) == len(instance_ids):
- break
-
- get_status_count += 1
- if get_status_count > 3:
- for i in instance_ids:
- if i not in instances_starting:
- self._logger.warning(WARNING_INSTANCE_NOT_STARTING, i)
- break
-
- if len(instances_starting) > 0:
- try:
- if stop_tags_keys is not None and len(stop_tags_keys) > 0:
- self._logger.info(
- INFO_REMOVING_KEYS,
- "stop",
- ",".join(
- ['"{}"'.format(k["Key"]) for k in stop_tags_keys]
- ),
- ",".join(instances_starting),
- )
- client.delete_tags(
- Resources=instances_starting, Tags=stop_tags_keys
- )
- if len(start_tags) > 0:
- self._logger.info(
- INF_ADD_KEYS,
- "start",
- str(start_tags),
- ",".join(instances_starting),
- )
- client.create_tags(
- Resources=instances_starting, Tags=start_tags
- )
- except Exception as ex:
- self._logger.warning(
- WARN_STARTED_INSTANCES_TAGGING,
- ",".join(instances_starting),
- str(ex),
- )
-
- for i in instances_starting:
- yield i, InstanceSchedule.STATE_RUNNING
-
- except Exception as ex:
- self._logger.error(
- ERR_STARTING_INSTANCES, ",".join(instance_ids), str(ex)
- )
diff --git a/source/app/instance_scheduler/schedulers/instance_scheduler.py b/source/app/instance_scheduler/schedulers/instance_scheduler.py
index 910de042..17a8a747 100644
--- a/source/app/instance_scheduler/schedulers/instance_scheduler.py
+++ b/source/app/instance_scheduler/schedulers/instance_scheduler.py
@@ -1,31 +1,31 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
+import time
+from collections.abc import Iterator
+from datetime import datetime, timezone
+from typing import Any, Final, Optional, TypedDict
+from typing_extensions import NotRequired
-from __future__ import print_function
-
-import os
-from datetime import datetime
-
-import boto3
-import json
-import pytz
-from botocore.exceptions import ClientError
-from instance_scheduler import configuration
-from instance_scheduler import schedulers
-from instance_scheduler.boto_retry import (
- get_client_with_standard_retry,
- standard_retries_client_config,
+from instance_scheduler import ScheduleState
+from instance_scheduler.configuration.instance_schedule import (
+ Instance,
+ InstanceSchedule,
+)
+from instance_scheduler.configuration.scheduling_context import SchedulingContext
+from instance_scheduler.ops_metrics.metric_type.instance_count_metric import (
+ InstanceCountMetric,
)
-from instance_scheduler.configuration.instance_schedule import InstanceSchedule
-from .instance_states import InstanceStates
-from instance_scheduler.util.metrics import send_metrics_data, allow_send_metrics
-from instance_scheduler.util.named_tuple_builder import as_namedtuple
+from instance_scheduler.ops_metrics.metric_type.scheduling_action_metric import (
+ ActionTaken,
+ SchedulingActionMetric,
+)
+from instance_scheduler.ops_metrics.metrics import collect_metric, should_collect_metric
+from instance_scheduler.schedulers.instance_states import InstanceStates
+from instance_scheduler.service import Service
+from instance_scheduler.util.logger import Logger
from instance_scheduler.util.scheduler_metrics import SchedulerMetrics
-ERR_ASSUMING_ROLE = "Can not assume role {} for account {}, ({}))"
-ERR_INVALID_ARN = "{} is not a valid ARN"
-ERR_INVALID_REGION = "{} is not a valid region name"
ERR_SETTING_INSTANCE_TYPE = "Error changing instance type ({})"
INF_DESIRED_TYPE = ", desired type is {}"
@@ -41,7 +41,6 @@
"state set to {} but instance will not be stopped if it is still running."
)
-WARN_DUPLICATE_ACCOUNT = "Account {} is already processed, skipping "
WARN_SKIPPING_UNKNOWN_SCHEDULE = (
'Skipping instance {} in region {} for account {}, schedule name "{}" is unknown'
)
@@ -75,269 +74,109 @@
)
-class InstanceScheduler:
- """
- Implements scheduler logic
- """
-
- def __init__(self, service, scheduler_configuration):
- """
- Initializes instance of instance scheduler
- :param service: service strategy that handles the actual listing, starting and stopping of the instances of that service
- """
- self._service = service
- self._instance_states = None
- self._schedule_metrics = None
- self._sts_client = None
- self._scheduled_instances = []
- self._configuration = None
- self._scheduler_start_list = []
- self._scheduler_stop_list = []
- self._schedule_resize_list = []
- self._scheduler_configuration = scheduler_configuration
- self._stack_name = os.getenv(configuration.ENV_STACK, "")
- self._lambda_account = os.getenv(configuration.ENV_ACCOUNT)
- self._logger = None
- self._context = None
- self._lambda_client = None
-
- self._usage_metrics = {"Started": {}, "Stopped": {}, "Resized": {}}
-
- @property
- def lambda_client(self):
- """
- Get the lambda client
- :return: lambda client
- """
- if self._lambda_client is None:
- self._lambda_client = get_client_with_standard_retry("lambda")
- return self._lambda_client
-
- @property
- def _regions(self):
- if len(self._configuration.regions) > 0:
- return self._configuration.regions
- else:
- # no regions, use region of lambda function
- return [boto3.Session().region_name]
-
- @property
- def _sts(self):
- if self._sts_client is None:
- session = boto3.Session()
- sts_regional_endpoint = str.format(
- "https://sts.{}.amazonaws.com", session.region_name
- )
- self._sts_client = session.client(
- "sts",
- region_name=session.region_name,
- endpoint_url=sts_regional_endpoint,
- config=standard_retries_client_config(),
- )
+class StartStopItem(TypedDict):
+ schedule: Optional[str]
- return self._sts_client
-
- def remove_account_from_config(self, aws_account, cross_account_role):
- """
- This method will invoke the lambda to remove the aws_account from the configuration, it calls the lambda handler eventbus_request_handler,
- and sends payload which will update the config by removing the account from further scheduling.
- {
- "account": 111122223333,
- "detail-type": "Parameter Store Change",
- "detail": {
- "operation": "Delete"
- }
- }
- :param aws_account: account where the assume role permission is not available for the lambda role to assume.
- :param cross_account_role: role name for logging message to SNS.
- """
- try:
- self._logger.error(
- "Removing the account {} from scheduling configuration as assume role permission is missing for the iam role {}".format(
- aws_account, cross_account_role
- )
- )
- payload = str.encode(
- json.dumps(
- {
- "account": aws_account,
- "detail-type": "Parameter Store Change",
- "detail": {"operation": "Delete"},
- }
- )
- )
- response = self.lambda_client.invoke(
- FunctionName=self._context.function_name,
- InvocationType="Event",
- LogType="None",
- Payload=payload,
- )
- self._logger.info(
- "Removing account {} from configuration".format(aws_account)
- )
- self._logger.debug(
- "Lambda response {} for removing account from configuration".format(
- response
- )
- )
- except Exception as ex:
- self._logger.error(
- "Error invoking lambda {} error {}".format(
- self._context.function_name, ex
- )
- )
- @property
- def _accounts(self):
- def get_session_for_account(cross_account_role, aws_account):
- # get a token for the cross account role and use it to create a session
- try:
- session_name = "{}-scheduler-{}".format(
- self._service.service_name, aws_account
- )
- # assume a role
- token = self._sts.assume_role(
- RoleArn=cross_account_role, RoleSessionName=session_name
- )
- credentials = token["Credentials"]
- # create a session using the assumed role credentials
- return boto3.Session(
- aws_access_key_id=credentials["AccessKeyId"],
- aws_secret_access_key=credentials["SecretAccessKey"],
- aws_session_token=credentials["SessionToken"],
- )
- except ClientError as ex:
- self._logger.error(
- "Error Code {}".format(ex.response.get("Error", {}).get("Code"))
- )
- if ex.response.get("Error", {}).get("Code") == "AccessDenied":
- self.remove_account_from_config(
- aws_account=aws_account, cross_account_role=cross_account_role
- )
- else:
- self._logger.error(
- ERR_ASSUMING_ROLE.format(
- cross_account_role, aws_account, str(ex)
- )
- )
- return None
+class ResizeItem(TypedDict):
+ schedule: Optional[str]
+ old: str
+ new: str
- # keep track of accounts processed
- accounts_done = []
- # return session for lambda account if processing instances in that account
- if self._configuration.schedule_lambda_account:
- accounts_done.append(self._lambda_account)
- yield as_namedtuple(
- "Account",
- {
- "session": boto3.Session(),
- "name": self._lambda_account,
- "role": None,
- },
- )
+StartStopItems = dict[str, list[dict[str, StartStopItem]]]
+ResizeItems = dict[str, list[dict[str, ResizeItem]]]
- # iterate through remote accounts
- for account in self._configuration.remote_account_ids:
- if account in accounts_done:
- self._logger.warning(WARN_DUPLICATE_ACCOUNT, account)
- continue
- # get a session for the role
- role = f"arn:{self._configuration.aws_partition}:iam::{account}:role/{self._configuration.namespace}-{self._configuration.scheduler_role_name}"
- session = get_session_for_account(role, account)
- if session is not None:
- yield as_namedtuple(
- "Account", {"session": session, "name": account, "role": role}
- )
+class ProcessAccountResult(TypedDict):
+ started: StartStopItems
+ stopped: StartStopItems
+ resized: NotRequired[ResizeItems]
+
- def _instance_display_str(self, inst_id, name):
+class InstanceScheduler:
+ def __init__(
+ self,
+ service: Service[Any],
+ scheduling_context: SchedulingContext,
+ instance_states: InstanceStates,
+ account_id: str,
+ role_arn: Optional[str],
+ logger: Logger,
+ ) -> None:
+ self._service: Final = service
+ self._scheduling_context: Final = scheduling_context
+ self._instance_states: Final = instance_states
+ self._account_id: Final = account_id
+ self._role_arn: Final = role_arn
+ self._logger: Final = logger
+
+ self._region: Final = self._scheduling_context.region
+
+ self._schedule_metrics: Final = SchedulerMetrics(datetime.now(timezone.utc))
+
+ self._scheduler_start_list: list[Instance] = []
+ self._scheduler_stop_list: list[Instance] = []
+ self._schedule_resize_list: list[tuple[Instance, str]] = []
+
+ self._usage_metrics: Final[dict[str, dict[str, Any]]] = {
+ "Started": {},
+ "Stopped": {},
+ "Resized": {},
+ }
+
+ def _instance_display_str(self, inst_id: str, name: str) -> str:
s = "{}:{}".format(self._service.service_name.upper(), inst_id)
if name:
s += " ({})".format(name)
return s
- def _scheduled_instances_in_region(self, account, region):
+ def _scheduled_instances_in_region(self) -> Iterator[Instance]:
# use service strategy to get a list of instances that can be scheduled for that service
- for instance in self._service.get_schedulable_instances(
- {
- schedulers.PARAM_SESSION: account.session,
- schedulers.PARAM_ACCOUNT: account.name,
- schedulers.PARAM_ROLE: account.role,
- schedulers.PARAM_REGION: region,
- schedulers.PARAM_CONFIG: self._configuration,
- schedulers.PARAM_LOGGER: self._logger,
- schedulers.PARAM_CONTEXT: self._context,
- }
- ):
- instance["account"] = account.name
- instance["region"] = region
+ for instance in self._service.get_schedulable_instances():
+ instance["account"] = self._account_id
+ instance["region"] = self._region
instance["service"] = self._service.service_name
instance["instance_str"] = self._instance_display_str(
instance["id"], instance["name"]
)
- inst = as_namedtuple(
- self._service.service_name + "Instance", instance, excludes=["tags"]
- )
- yield inst
-
- def run(
- self, state_table, scheduler_config, logger, lambda_account=None, context=None
- ):
- """
- Runs the scheduler for a service
- :param state_table: name of the instance state table
- :param scheduler_config: scheduler configuration data
- :param logger: logger to log output of scheduling process
- :param lambda_account: lambda account
- :param context: Lambda context
- :return:
- """
-
- self._lambda_account = lambda_account
- self._configuration = scheduler_config
- self._logger = logger
- self._context = context
- self._logger.debug_enabled = self._configuration.trace
-
- # stored instance desired states
- self._instance_states = InstanceStates(
- state_table, self._service.service_name, self._logger, self._context
- )
-
- # time to use for metrics
- self._schedule_metrics = SchedulerMetrics(datetime.utcnow(), self._context)
+ yield instance
- # response to caller, contains list off all processed accounts with started and stopped instances
- response = {}
+ def run(self) -> Any:
+ execution_start = time.perf_counter()
+ response, instances = self._process_account()
+ execution_end = time.perf_counter()
- for account in self._accounts:
- response[account.name] = self._process_account(account)
-
- if allow_send_metrics():
- self._send_usage_metrics()
+ time_taken = execution_end - execution_start
+ self._collect_op_metrics(instances=instances, time_taken=time_taken)
return response
- def get_desired_state_and_type(self, schedule, instance):
+ def get_desired_state_and_type(
+ self, schedule: InstanceSchedule, instance: Instance
+ ) -> tuple[ScheduleState, Optional[str]]:
# test if the instance has a maintenance window in which it must be running
if (
- instance.maintenance_window is not None
+ instance["maintenance_window"] is not None
and schedule.use_maintenance_window is True
):
self._logger.info(
- INF_MAINTENANCE_WINDOW, instance.maintenance_window.name, instance.id
+ INF_MAINTENANCE_WINDOW,
+ instance["maintenance_window"].name,
+ instance["id"],
)
# get the desired start for the maintenance window at current UTC time
(
inst_state,
inst_type,
- running_period,
- ) = instance.maintenance_window.get_desired_state(
+ _,
+ ) = instance["maintenance_window"].get_desired_state(
instance,
logger=self._logger,
- dt=datetime.utcnow().replace(tzinfo=pytz.timezone("UTC")),
+ dt=datetime.now(
+ timezone.utc
+ ), # todo: using current time instead of schedule time?
)
# if we're in the maintenance window return running state
@@ -346,160 +185,111 @@ def get_desired_state_and_type(self, schedule, instance):
# based on the schedule get the desired state and instance type for this instance
inst_state, inst_type, _ = schedule.get_desired_state(
- instance, logger=self._logger
+ instance, logger=self._logger, dt=self._scheduling_context.current_dt
)
return inst_state, inst_type
- def _process_account(self, account):
- # processes instances for a service in an account
- started_instances = {}
- stopped_instances = {}
- resized_instances = {}
+ def _process_account(self) -> tuple[ProcessAccountResult, list[Instance]]:
+ started_instances: StartStopItems = {}
+ stopped_instances: StartStopItems = {}
+ resized_instances: ResizeItems = {}
self._logger.info(
INF_PROCESSING_ACCOUNT,
self._service.service_name.upper(),
- account.name,
- " using role " + account.role if account.role else "",
- ", ".join(self._configuration.regions),
+ self._account_id,
+ " using role " + (self._role_arn or ""),
+ self._region,
)
- for region in self._regions:
- state_loaded = False
- instances = []
-
- self._scheduler_start_list = []
- self._scheduler_stop_list = []
- self._schedule_resize_list = []
-
- for instance in self._scheduled_instances_in_region(account, region):
- # delay loading instance state until first instance is returned
- if not state_loaded:
- self._instance_states.load(account.name, region)
- state_loaded = True
+ state_loaded = False
+ instances: list[Instance] = []
- instances.append(instance)
+ self._scheduler_start_list = []
+ self._scheduler_stop_list = []
+ self._schedule_resize_list = []
- # handle terminated instances
- if instance.is_terminated:
- self._logger.debug(
- DEBUG_SKIPPING_TERMINATED_INSTANCE,
- instance.instance_str,
- region,
- instance.account,
- )
- self._instance_states.delete_instance_state(instance.id)
- continue
+ for instance in self._scheduled_instances_in_region():
+ # delay loading instance state until first instance is returned
+ if not state_loaded:
+ self._instance_states.load(self._account_id, self._region)
+ state_loaded = True
- # get the schedule for this instance
- instance_schedule = self._configuration.get_schedule(
- instance.schedule_name
- )
- if not instance_schedule:
- self._logger.warning(
- WARN_SKIPPING_UNKNOWN_SCHEDULE,
- instance.instance_str,
- region,
- instance.account,
- instance.schedule_name,
- )
- continue
+ instances.append(instance)
- self._logger.debug(DEBUG_INSTANCE_HEADER, instance.instance_str)
+ # handle terminated instances
+ if instance["is_terminated"]:
self._logger.debug(
- DEBUG_CURRENT_INSTANCE_STATE,
- instance.current_state,
- instance.instancetype,
- instance_schedule.name,
+ DEBUG_SKIPPING_TERMINATED_INSTANCE,
+ instance["instance_str"],
+ self._region,
+ instance["account"],
)
+ self._instance_states.delete_instance_state(instance["id"])
+ continue
- # based on the schedule get the desired state and instance type for this instance
- desired_state, desired_type = self.get_desired_state_and_type(
- instance_schedule, instance
+ # get the schedule for this instance
+ instance_schedule = self._scheduling_context.get_schedule(
+ instance["schedule_name"]
+ )
+ if not instance_schedule:
+ self._logger.warning(
+ WARN_SKIPPING_UNKNOWN_SCHEDULE,
+ instance["instance_str"],
+ self._region,
+ instance["account"],
+ instance["schedule_name"],
)
+ continue
- # get the previous desired instance state
- last_desired_state = self._instance_states.get_instance_state(
- instance.id
- )
- self._logger.debug(
- DEBUG_CURRENT_AND_DESIRED_STATE,
- instance_schedule.name,
- desired_state,
- last_desired_state,
- instance.current_state,
- INF_DESIRED_TYPE.format(desired_type) if desired_type else "",
- )
+ self._logger.debug(DEBUG_INSTANCE_HEADER, instance["instance_str"])
+ self._logger.debug(
+ DEBUG_CURRENT_INSTANCE_STATE,
+ instance["current_state"],
+ instance["instancetype"],
+ instance_schedule.name,
+ )
- # last desired state None means this is the first time the instance is seen by the scheduler
- if last_desired_state is InstanceSchedule.STATE_UNKNOWN:
- # new instances that are running are optionally not stopped to allow them to finish possible initialization
- if (
- instance.is_running
- and desired_state == InstanceSchedule.STATE_STOPPED
- ):
- if not instance_schedule.stop_new_instances:
- self._instance_states.set_instance_state(
- instance.id, InstanceSchedule.STATE_STOPPED
- )
- self._logger.debug(
- DEBUG_NEW_INSTANCE, instance.instance_str
- )
- continue
- self._process_new_desired_state(
- account,
- region,
- instance,
- desired_state,
- desired_type,
- last_desired_state,
- instance_schedule.retain_running,
- )
- else:
- self._process_new_desired_state(
- account,
- region,
- instance,
- desired_state,
- desired_type,
- last_desired_state,
- instance_schedule.retain_running,
- )
+ # based on the schedule get the desired state and instance type for this instance
+ desired_state, desired_type = self.get_desired_state_and_type(
+ instance_schedule, instance
+ )
- # existing instance
-
- # if enforced check the actual state with the desired state enforcing the schedule state
- elif instance_schedule.enforced:
- if (
- instance.is_running
- and desired_state == InstanceSchedule.STATE_STOPPED
- ) or (
- not instance.is_running
- and desired_state == InstanceSchedule.STATE_RUNNING
- ):
- self._logger.debug(
- DEBUG_ENFORCED_STATE,
- instance.instance_str,
- InstanceSchedule.STATE_RUNNING
- if instance.is_running
- else InstanceSchedule.STATE_STOPPED,
- desired_state,
- )
- self._process_new_desired_state(
- account,
- region,
- instance,
- desired_state,
- desired_type,
- last_desired_state,
- instance_schedule.retain_running,
+ # get the previous desired instance state
+ last_desired_state = self._instance_states.get_instance_state(
+ instance["id"]
+ )
+ self._logger.debug(
+ DEBUG_CURRENT_AND_DESIRED_STATE,
+ instance_schedule.name,
+ desired_state,
+ last_desired_state,
+ instance["current_state"],
+ INF_DESIRED_TYPE.format(desired_type) if desired_type else "",
+ )
+
+ # last desired state None means this is the first time the instance is seen by the scheduler
+ if last_desired_state is InstanceSchedule.STATE_UNKNOWN:
+ # new instances that are running are optionally not stopped to allow them to finish possible initialization
+ if (
+ instance["is_running"]
+ and desired_state == InstanceSchedule.STATE_STOPPED
+ ):
+ if not instance_schedule.stop_new_instances:
+ self._instance_states.set_instance_state(
+ instance["id"], InstanceSchedule.STATE_STOPPED
)
- # if not enforced then compare the schedule state with the actual state so state of manually started/stopped
- # instance it will honor that state
- elif last_desired_state != desired_state:
+ self._logger.debug(DEBUG_NEW_INSTANCE, instance["instance_str"])
+ continue
+ self._process_new_desired_state(
+ instance,
+ desired_state,
+ desired_type,
+ last_desired_state,
+ instance_schedule.retain_running,
+ )
+ else:
self._process_new_desired_state(
- account,
- region,
instance,
desired_state,
desired_type,
@@ -507,138 +297,116 @@ def _process_account(self, account):
instance_schedule.retain_running,
)
- self._schedule_metrics.add_schedule_metrics(
- self._service.service_name, instance_schedule, instance
+ # existing instance
+
+ # if enforced check the actual state with the desired state enforcing the schedule state
+ elif instance_schedule.enforced:
+ if (
+ instance["is_running"]
+ and desired_state == InstanceSchedule.STATE_STOPPED
+ ) or (
+ not instance["is_running"]
+ and desired_state == InstanceSchedule.STATE_RUNNING
+ ):
+ self._logger.debug(
+ DEBUG_ENFORCED_STATE,
+ instance["instance_str"],
+ InstanceSchedule.STATE_RUNNING
+ if instance["is_running"]
+ else InstanceSchedule.STATE_STOPPED,
+ desired_state,
+ )
+ self._process_new_desired_state(
+ instance,
+ desired_state,
+ desired_type,
+ last_desired_state,
+ instance_schedule.retain_running,
+ )
+ # if not enforced then compare the schedule state with the actual state so state of manually started/stopped
+ # instance it will honor that state
+ elif last_desired_state != desired_state:
+ self._process_new_desired_state(
+ instance,
+ desired_state,
+ desired_type,
+ last_desired_state,
+ instance_schedule.retain_running,
)
- # process lists of instances that must be started or stopped
- self._start_and_stop_instances(account, region=region)
-
- # cleanup desired instance states and save
- self._instance_states.cleanup([i.id for i in instances])
- self._instance_states.save()
-
- # build output structure, hold started, stopped and resized instances per region
- if len(self._scheduler_start_list) > 0:
- started_instances[region] = [
- {i.id: {"schedule": i.schedule_name}}
- for i in self._scheduler_start_list
- ]
- if len(self._scheduler_stop_list):
- stopped_instances[region] = [
- {i.id: {"schedule": i.schedule_name}}
- for i in self._scheduler_stop_list
- ]
- if len(self._schedule_resize_list) > 0:
- resized_instances[region] = [
- {
- i[0].id: {
- "schedule": i[0].schedule_name,
- "old": i[0].instancetype,
- "new": i[1],
- }
+ self._schedule_metrics.add_schedule_metrics(
+ self._service.service_name, instance_schedule, instance
+ )
+
+ # process lists of instances that must be started or stopped
+ self._start_and_stop_instances()
+
+ # cleanup desired instance states and save
+ self._instance_states.cleanup([i["id"] for i in instances])
+ self._instance_states.save()
+
+ # build output structure, hold started, stopped and resized instances per region
+ if len(self._scheduler_start_list) > 0:
+ started_instances[self._region] = [
+ {i["id"]: {"schedule": i["schedule_name"]}}
+ for i in self._scheduler_start_list
+ ]
+ if len(self._scheduler_stop_list):
+ stopped_instances[self._region] = [
+ {i["id"]: {"schedule": i["schedule_name"]}}
+ for i in self._scheduler_stop_list
+ ]
+ if len(self._schedule_resize_list) > 0:
+ resized_instances[self._region] = [
+ {
+ i[0]["id"]: {
+ "schedule": i[0]["schedule_name"],
+ "old": i[0]["instancetype"],
+ "new": i[1],
}
- for i in self._schedule_resize_list
- ]
- if allow_send_metrics():
- self._collect_usage_metrics()
+ }
+ for i in self._schedule_resize_list
+ ]
# put cloudwatch metrics
- if self._configuration.use_metrics:
+ if self._scheduling_context.use_metrics:
self._schedule_metrics.put_schedule_metrics()
# output data
- result = {"started": started_instances, "stopped": stopped_instances}
+ result: ProcessAccountResult = {
+ "started": started_instances,
+ "stopped": stopped_instances,
+ }
if self._service.allow_resize:
result["resized"] = resized_instances
- return result
-
- def _send_usage_metrics(self):
- usage_data = []
- for s in list(self._usage_metrics):
- if len(self._usage_metrics[s]) == 0:
- del self._usage_metrics[s]
- if len(self._usage_metrics) > 0:
- for action in self._usage_metrics:
- for instance_type in self._usage_metrics.get(action, {}):
- usage_data.append(
- {
- "Service": self._service.service_name,
- "Action": action,
- "InstanceType": instance_type,
- "Instances": self._usage_metrics[action][instance_type],
- }
- )
-
- send_metrics_data(usage_data, logger=self._logger)
-
- def _collect_usage_metrics(self):
- for i in self._scheduler_start_list:
- if i.id in [r[0].id for r in self._schedule_resize_list]:
- instance_type = [
- r[1] for r in self._schedule_resize_list if r[0].id == i.id
- ][0]
- else:
- instance_type = i.instancetype
- if instance_type in self._usage_metrics["Started"]:
- self._usage_metrics["Started"][instance_type] += 1
- else:
- self._usage_metrics["Started"][instance_type] = 1
-
- for i in self._scheduler_stop_list:
- if i.instancetype in self._usage_metrics["Stopped"]:
- self._usage_metrics["Stopped"][i.instancetype] += 1
- else:
- self._usage_metrics["Stopped"][i.instancetype] = 1
-
- for i in self._schedule_resize_list:
- type_change = "{}-{}".format(i[0].instancetype, i[1])
- if type_change in self._usage_metrics["Resized"]:
- self._usage_metrics["Resized"][type_change] += 1
- else:
- self._usage_metrics["Resized"][type_change] = 1
+ return result, instances
# handle new state of an instance
def _process_new_desired_state(
self,
- account,
- region,
- instance,
- desired_state,
- desired_type,
- last_desired_state,
- retain_running,
- ):
- def need_and_can_resize():
- if desired_type is not None and instance.instancetype != desired_type:
- if not instance.allow_resize:
+ instance: Instance,
+ desired_state: str,
+ desired_type: Optional[str],
+ last_desired_state: str,
+ retain_running: Optional[bool],
+ ) -> None:
+ def need_and_can_resize() -> bool:
+ if desired_type is not None and instance["instancetype"] != desired_type:
+ if not instance["allow_resize"]:
self._logger.warning(
WARN_RESIZE_NOT_SUPPORTED,
- instance.instance_str,
- instance.instancetype,
+ instance["instance_str"],
+ instance["instancetype"],
)
return False
else:
return True
return False
- def resize_instance(inst, new_type):
+ def resize_instance(inst: Instance, new_type: str) -> None:
try:
# adjust instance type before starting using the resize_instance method in the service_strategy
- self._service.resize_instance(
- {
- schedulers.PARAM_SESSION: account.session,
- schedulers.PARAM_ACCOUNT: account.name,
- schedulers.PARAM_ROLE: account.role,
- schedulers.PARAM_REGION: region,
- schedulers.PARAM_TRACE: self._configuration.trace,
- schedulers.PARAM_INSTANCE: instance,
- schedulers.PARAM_DESIRED_TYPE: new_type,
- schedulers.PARAM_LOGGER: self._logger,
- schedulers.PARAM_CONTEXT: self._context,
- schedulers.PARAM_CONFIG: self._scheduler_configuration,
- }
- )
+ self._service.resize_instance(instance, new_type)
self._schedule_resize_list.append((inst, new_type))
except Exception as ex:
@@ -649,39 +417,41 @@ def resize_instance(inst, new_type):
if last_desired_state == InstanceSchedule.STATE_RETAIN_RUNNING:
# don't change last desired state desired whilst in a running period
if desired_state == InstanceSchedule.STATE_RUNNING:
- pass
+ pass # todo: should this be a return?
# save last desired state as stopped (but do not stop) at the end of running period
elif desired_state == InstanceSchedule.STATE_STOPPED:
# safe new desired stopped state but keep running
self._logger.debug(
INF_DO_NOT_STOP_RETAINED_INSTANCE,
- instance.id,
+ instance["id"],
InstanceSchedule.STATE_STOPPED,
)
self._instance_states.set_instance_state(
- instance.id, InstanceSchedule.STATE_STOPPED
+ instance["id"], InstanceSchedule.STATE_STOPPED
)
else:
# just save new desired state
- self._instance_states.set_instance_state(instance.id, desired_state)
+ self._instance_states.set_instance_state(instance["id"], desired_state)
else:
if desired_state == InstanceSchedule.STATE_RUNNING:
- if not instance.is_running:
+ if not instance["is_running"]:
inst_type = (
desired_type
if desired_type is not None
- else instance.instancetype
+ else instance["instancetype"]
)
self._logger.debug(
DEBUG_STARTED_REGION_INSTANCES,
- instance.instance_str,
- instance.region,
+ instance["instance_str"],
+ instance["region"],
inst_type,
)
# for instances to be started test if resizing is required
if need_and_can_resize():
+ if not desired_type:
+ raise ValueError("Tried to resize with no desired type")
resize_instance(instance, desired_type)
# append instance to list of instances to start
@@ -695,16 +465,16 @@ def resize_instance(inst, new_type):
self._logger.debug(
DEBUG_APPLY_RETAIN_RUNNING_STATE,
desired_state,
- instance.id,
+ instance["id"],
InstanceSchedule.STATE_RETAIN_RUNNING,
)
self._instance_states.set_instance_state(
- instance.id, InstanceSchedule.STATE_RETAIN_RUNNING
+ instance["id"], InstanceSchedule.STATE_RETAIN_RUNNING
)
else:
# instance is running, set last desired state from stopped to started
self._instance_states.set_instance_state(
- instance.id, InstanceSchedule.STATE_RUNNING
+ instance["id"], InstanceSchedule.STATE_RUNNING
)
# desired state is running but saved state already saves as retain running
@@ -713,50 +483,39 @@ def resize_instance(inst, new_type):
InstanceSchedule.STATE_STOPPED,
InstanceSchedule.STATE_STOPPED_FOR_RESIZE,
]:
- if instance.is_running:
+ if instance["is_running"]:
# instance needs to be stopped
self._logger.debug(
DEBUG_STOPPED_REGION_INSTANCES,
- instance.instance_str,
- instance.region,
+ instance["instance_str"],
+ instance["region"],
)
# append instance to list of instances to start
if desired_state == InstanceSchedule.STATE_STOPPED_FOR_RESIZE:
- instance = instance._replace(resized=True)
+ instance["resized"] = True
self._scheduler_stop_list.append(instance)
# stopped instance with desired state of running but in retained state mode
# (manually stopped in running period and already running at start)
else:
# just save new desired state
self._instance_states.set_instance_state(
- instance.id, InstanceSchedule.STATE_STOPPED
+ instance["id"], InstanceSchedule.STATE_STOPPED
)
else:
- self._instance_states.set_instance_state(instance.id, desired_state)
+ self._instance_states.set_instance_state(instance["id"], desired_state)
# start and stop listed instances
- def _start_and_stop_instances(self, account, region):
+ def _start_and_stop_instances(self) -> None:
if len(self._scheduler_start_list) > 0:
self._logger.info(
INF_STARTING_INSTANCES,
- ", ".join([i.instance_str for i in self._scheduler_start_list]),
- region,
+ ", ".join([i["instance_str"] for i in self._scheduler_start_list]),
+ self._region,
)
for inst_id, state in self._service.start_instances(
- {
- schedulers.PARAM_SESSION: account.session,
- schedulers.PARAM_ACCOUNT: account.name,
- schedulers.PARAM_ROLE: account.role,
- schedulers.PARAM_REGION: region,
- schedulers.PARAM_TRACE: self._configuration.trace,
- schedulers.PARAM_STARTED_INSTANCES: self._scheduler_start_list,
- schedulers.PARAM_LOGGER: self._logger,
- schedulers.PARAM_CONTEXT: self._context,
- schedulers.PARAM_STACK: self._stack_name,
- schedulers.PARAM_CONFIG: self._scheduler_configuration,
- }
+ self._scheduler_start_list
):
# set state based on returned state from start action
self._instance_states.set_instance_state(inst_id, state)
@@ -764,22 +523,94 @@ def _start_and_stop_instances(self, account, region):
if len(self._scheduler_stop_list) > 0:
self._logger.info(
INF_STOPPED_INSTANCES,
- ", ".join([i.instance_str for i in self._scheduler_stop_list]),
- region,
+ ", ".join([i["instance_str"] for i in self._scheduler_stop_list]),
+ self._region,
)
for inst_id, state in self._service.stop_instances(
- {
- schedulers.PARAM_SESSION: account.session,
- schedulers.PARAM_ACCOUNT: account.name,
- schedulers.PARAM_ROLE: account.role,
- schedulers.PARAM_REGION: region,
- schedulers.PARAM_TRACE: self._configuration.trace,
- schedulers.PARAM_STOPPED_INSTANCES: self._scheduler_stop_list,
- schedulers.PARAM_LOGGER: self._logger,
- schedulers.PARAM_CONTEXT: self._context,
- schedulers.PARAM_STACK: self._stack_name,
- schedulers.PARAM_CONFIG: self._scheduler_configuration,
- }
+ self._scheduler_stop_list
):
# set state based on start of stop action
self._instance_states.set_instance_state(inst_id, state)
+
+ # ------------------------METRICS--------------------------------#
+ def _collect_op_metrics(self, instances: list[Instance], time_taken: float) -> None:
+ if should_collect_metric(InstanceCountMetric, self._logger):
+ self._collect_instance_count_metric(instances)
+
+ if should_collect_metric(SchedulingActionMetric, self._logger):
+ self._collect_scheduling_actions_metric(time_taken)
+
+ def _collect_instance_count_metric(self, instances: list[Instance]) -> None:
+ collect_metric(
+ InstanceCountMetric(
+ service=self._scheduling_context.service,
+ region=self._scheduling_context.region,
+ num_instances=len(instances),
+ num_schedules=self._count_unique_schedules(instances),
+ ),
+ logger=self._logger,
+ )
+
+ def _collect_scheduling_actions_metric(self, time_taken: float) -> None:
+ self._collect_usage_metrics()
+ self._send_usage_metrics(time_taken)
+
+ @staticmethod
+ def _count_unique_schedules(instances: list[Instance]) -> int:
+ schedules = set()
+ for instance in instances:
+ schedules.add(instance.get("schedule_name"))
+
+ return len(schedules)
+
+ def _collect_usage_metrics(self) -> None:
+ for i in self._scheduler_start_list:
+ if i["id"] in [r[0]["id"] for r in self._schedule_resize_list]:
+ instance_type = [
+ r[1] for r in self._schedule_resize_list if r[0]["id"] == i["id"]
+ ][0]
+ else:
+ instance_type = i["instancetype"]
+ if instance_type in self._usage_metrics["Started"]:
+ self._usage_metrics["Started"][instance_type] += 1
+ else:
+ self._usage_metrics["Started"][instance_type] = 1
+
+ for i in self._scheduler_stop_list:
+ if i["instancetype"] in self._usage_metrics["Stopped"]:
+ self._usage_metrics["Stopped"][i["instancetype"]] += 1
+ else:
+ self._usage_metrics["Stopped"][i["instancetype"]] = 1
+
+ for resized_instance in self._schedule_resize_list:
+ type_change = "{}-{}".format(
+ resized_instance[0]["instancetype"], resized_instance[1]
+ )
+ if type_change in self._usage_metrics["Resized"]:
+ self._usage_metrics["Resized"][type_change] += 1
+ else:
+ self._usage_metrics["Resized"][type_change] = 1
+
+ def _send_usage_metrics(self, time_taken: float) -> None:
+ for s in list(self._usage_metrics):
+ if len(self._usage_metrics[s]) == 0:
+ del self._usage_metrics[s]
+ if len(self._usage_metrics) > 0:
+ actions_taken = []
+ for action in self._usage_metrics:
+ for instance_type in self._usage_metrics.get(action, {}):
+ actions_taken.append(
+ ActionTaken(
+ instances=self._usage_metrics[action][instance_type],
+ action=action,
+ instanceType=instance_type,
+ service=self._service.service_name,
+ )
+ )
+
+ collect_metric(
+ SchedulingActionMetric(
+ duration_seconds=time_taken, actions=actions_taken
+ ),
+ logger=self._logger,
+ )
diff --git a/source/app/instance_scheduler/schedulers/instance_states.py b/source/app/instance_scheduler/schedulers/instance_states.py
index 003aa393..20384bc5 100644
--- a/source/app/instance_scheduler/schedulers/instance_states.py
+++ b/source/app/instance_scheduler/schedulers/instance_states.py
@@ -1,14 +1,14 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-
import time
from decimal import Decimal
+from typing import Any, Optional
-import boto3
from botocore.exceptions import ClientError
-from instance_scheduler.util.dynamodb_utils import DynamoDBUtils
+
from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler.util.dynamodb_utils import DynamoDBUtils
+from instance_scheduler.util.logger import Logger
INF_CLEANING = "Cleaning up instance registry."
INF_MOVING_FOR_PURGE = "Moving instance {} to be purged in next cleanup."
@@ -17,7 +17,6 @@
WARN_LOADING_STATE = "Could not load instance state data {}, this warning should only occur once after creating the scheduler"
-# noinspection SpellCheckingInspection,SpellCheckingInspection,SpellCheckingInspection,SpellCheckingInspection,SpellCheckingInspection,SpellCheckingInspection,SpellCheckingInspection
class InstanceStates:
"""
Implements store for last desired state for service instances
@@ -31,27 +30,25 @@ class InstanceStates:
# cleanup interval time
cleanup_interval = Decimal(12 * 3600)
- def __init__(self, table_name, service, logger, context):
+ def __init__(self, table_name: str, service: str, logger: Logger) -> None:
"""
Initializes instance of state store
:param table_name: name of the state table
:param service: name of the service
:param logger: logger to log output of ste logic
- :param context: lambda context
"""
self._table_name = table_name
self._state_table = None
- self._state_info = {}
- self._instances_to_purge = set()
- self._dirty = None
- self._timestamp = Decimal(time.time())
+ self._state_info: dict[str, Any] = {}
+ self._instances_to_purge: set[Any] = set()
+ self._dirty: Optional[bool] = None
+ self._timestamp: Decimal | float = Decimal(time.time())
self._service = service
- self._current_account_region = None
+ self._current_account_region: Optional[str] = None
self._logger = logger
- self._context = context
@property
- def state_table(self):
+ def state_table(self) -> Any:
"""
Returns state table dynamodb table resource
:return:
@@ -62,7 +59,7 @@ def state_table(self):
)
return self._state_table
- def load(self, account, region):
+ def load(self, account: str, region: str) -> None:
"""
Loads the desired state for the specified account and service
:param account: account to load state for
@@ -110,7 +107,7 @@ def load(self, account, region):
if InstanceStates.INSTANCE_TABLE_PURGE in item:
self._instances_to_purge = item[InstanceStates.INSTANCE_TABLE_PURGE]
- def set_instance_state(self, instance_id, new_state):
+ def set_instance_state(self, instance_id: str, new_state: str) -> None:
"""
Sets the state of an instance
:param instance_id: id of the instance
@@ -133,7 +130,7 @@ def get_instance_state(self, instance_id):
state = self._state_info.get(instance_id, None)
return state if state else InstanceSchedule.STATE_UNKNOWN
- def delete_instance_state(self, instance_id):
+ def delete_instance_state(self, instance_id: str) -> None:
"""
Removes the state of an instance
:param instance_id: id of the instance
@@ -145,14 +142,14 @@ def delete_instance_state(self, instance_id):
self._instances_to_purge.remove(instance_id)
self._dirty = True
- def save(self):
+ def save(self) -> None:
"""
Stores the instance state information to the dynamodb table if it has changed
:return:
"""
if self._dirty:
# key and timestamp
- data = {
+ data: dict[str, Any] = {
InstanceStates.INSTANCE_TABLE_NAME: self._service,
InstanceStates.INSTANCE_TABLE_ACCOUNT_REGION: self._current_account_region,
InstanceStates.INSTANCE_TABLE_TIMESTAMP: Decimal(time.time()),
@@ -169,7 +166,7 @@ def save(self):
self.state_table.put_item(Item=data)
self._dirty = False
- def cleanup(self, instances):
+ def cleanup(self, instances: list[str]) -> None:
"""
Removes instance id's from the table that have been terminated or not being processed by the scheduler.
This code contains workaround for instances not being returned by describe_instances when changing state
diff --git a/source/app/instance_scheduler/service/__init__.py b/source/app/instance_scheduler/service/__init__.py
new file mode 100644
index 00000000..07855338
--- /dev/null
+++ b/source/app/instance_scheduler/service/__init__.py
@@ -0,0 +1,22 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from collections.abc import Mapping as _Mapping
+from typing import Any as _Any
+from typing import Final as _Final
+
+from .base import Service, ServiceArgs
+from .ec2 import Ec2Service
+from .rds import RdsService
+
+services: _Final[_Mapping[str, type[Service[_Any]]]] = {
+ "ec2": Ec2Service,
+ "rds": RdsService,
+}
+
+__all__ = [
+ "Ec2Service",
+ "Service",
+ "ServiceArgs",
+ "services",
+ "RdsService",
+]
diff --git a/source/app/instance_scheduler/service/base.py b/source/app/instance_scheduler/service/base.py
new file mode 100644
index 00000000..b7a24f0f
--- /dev/null
+++ b/source/app/instance_scheduler/service/base.py
@@ -0,0 +1,58 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from abc import ABC, abstractmethod
+from collections.abc import Iterator
+from typing import Generic, TypedDict, TypeVar
+
+from boto3.session import Session
+
+from instance_scheduler import ScheduleState
+from instance_scheduler.configuration.instance_schedule import Instance
+from instance_scheduler.configuration.scheduling_context import SchedulingContext
+from instance_scheduler.util.logger import Logger
+
+
+class ServiceArgs(TypedDict):
+ account_id: str
+ logger: Logger
+ stack_name: str
+ session: Session
+ scheduling_context: SchedulingContext
+
+
+T = TypeVar("T", bound=Instance)
+
+
+class Service(Generic[T], ABC):
+ def __init__(self, _: ServiceArgs) -> None:
+ """noop"""
+
+ @property
+ @abstractmethod
+ def service_name(self) -> str:
+ pass
+
+ @property
+ @abstractmethod
+ def allow_resize(self) -> bool:
+ pass
+
+ @abstractmethod
+ def get_schedulable_instances(self) -> list[T]:
+ pass
+
+ @abstractmethod
+ def start_instances(
+ self, instances_to_start: list[T]
+ ) -> Iterator[tuple[str, ScheduleState]]:
+ pass
+
+ @abstractmethod
+ def stop_instances(
+ self, instances_to_stop: list[T]
+ ) -> Iterator[tuple[str, ScheduleState]]:
+ pass
+
+ @abstractmethod
+ def resize_instance(self, instance: T, instance_type: str) -> None:
+ pass
diff --git a/source/app/instance_scheduler/service/ec2.py b/source/app/instance_scheduler/service/ec2.py
new file mode 100644
index 00000000..1121a654
--- /dev/null
+++ b/source/app/instance_scheduler/service/ec2.py
@@ -0,0 +1,381 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from collections.abc import Iterator
+from enum import IntEnum
+from itertools import chain
+from typing import TYPE_CHECKING, Final, Literal
+
+from boto3 import Session
+
+from instance_scheduler import ScheduleState
+from instance_scheduler.configuration.instance_schedule import (
+ Instance,
+ InstanceSchedule,
+)
+from instance_scheduler.configuration.scheduling_context import TagTemplate
+from instance_scheduler.maint_win import EC2SSMMaintenanceWindows
+from instance_scheduler.service import Service, ServiceArgs
+from instance_scheduler.util import get_boto_config
+from instance_scheduler.util.app_env import get_app_env
+from instance_scheduler.util.batch import FailureResponse, bisect_retry
+
+if TYPE_CHECKING:
+ from mypy_boto3_ec2.client import EC2Client
+ from mypy_boto3_ec2.literals import InstanceStateNameType
+ from mypy_boto3_ec2.type_defs import FilterTypeDef, InstanceTypeDef, TagTypeDef
+else:
+ EC2Client = object
+ InstanceStateNameType = object
+ FilterTypeDef = object
+ InstanceTypeDef = object
+ TagTypeDef = object
+
+
+class EC2StateCode(IntEnum):
+ PENDING = 0x00
+ RUNNING = 0x10
+ SHUTTING_DOWN = 0x20
+ TERMINATED = 0x30
+ STOPPING = 0x40
+ STOPPED = 0x50
+
+
+def get_tags(instance: InstanceTypeDef) -> dict[str, str]:
+ return {tag["Key"]: tag["Value"] for tag in instance.get("Tags", [])}
+
+
+class Ec2Service(Service[Instance]):
+ def __init__(self, args: ServiceArgs) -> None:
+ Service.__init__(self, args)
+
+ self._spoke_session: Final = args["session"]
+ self._spoke_account_id: Final = args["account_id"]
+ self._logger: Final = args["logger"]
+ self._scheduling_context: Final = args["scheduling_context"]
+
+ self._spoke_region: Final = self._spoke_session.region_name
+ self._scheduler_tag_key: Final = self._scheduling_context.tag_name
+
+ self._ec2: Final[EC2Client] = self._spoke_session.client(
+ "ec2", config=get_boto_config()
+ )
+
+ self._maintenance_window_schedules: dict[
+ str, InstanceSchedule | Literal["NOT-FOUND"]
+ ] = {}
+
+ app_env: Final = get_app_env()
+
+ self._maintenance_windows = EC2SSMMaintenanceWindows(
+ hub_session=Session(),
+ spoke_account_id=self._spoke_account_id,
+ spoke_session=self._spoke_session,
+ table_name=app_env.maintenance_window_table_name,
+ scheduler_interval=app_env.scheduler_frequency_minutes,
+ logger=self._logger,
+ )
+
+ @property
+ def service_name(self) -> str:
+ return "ec2"
+
+ @property
+ def allow_resize(self) -> bool:
+ return True
+
+ def get_schedulable_instances(self) -> list[Instance]:
+ """
+ describe all EC2 instances in the target region and return `Instance` data for
+ each instance that is schedulable
+
+ an instance is schedulable if it satisifes:
+ - in the `running` or `stopped` state
+ - tagged with the schedule tag key
+
+ also describe all maintenance windows, reconcile the DB with the service, and
+ create `InstanceSchedule`s for each window
+ """
+ schedules_with_hibernation: Final = frozenset(
+ s.name for s in self._scheduling_context.schedules.values() if s.hibernate
+ )
+
+ self._logger.info(
+ "Enable SSM Maintenance window is set to {}",
+ self._scheduling_context.enable_ssm_maintenance_windows,
+ )
+ if self._scheduling_context.enable_ssm_maintenance_windows:
+ # calling the get maintenance window for this account and region.
+ self._logger.info(
+ "load the ssm maintenance windows for account {}, and region {}",
+ self._spoke_account_id,
+ self._spoke_region,
+ )
+ self._maintenance_window_schedules = (
+ self._maintenance_windows.ssm_maintenance_windows(
+ self._spoke_session, self._spoke_account_id, self._spoke_region
+ )
+ )
+ self._logger.info("finish loading the ssm maintenance windows")
+
+ self._logger.info(
+ "Fetching ec2 instances for account {} in region {}",
+ self._spoke_account_id,
+ self._spoke_region,
+ )
+
+ paginator: Final = self._ec2.get_paginator("describe_instances")
+ schedulable_states: Final[list[InstanceStateNameType]] = ["running", "stopped"]
+ filters: Final[list[FilterTypeDef]] = [
+ {"Name": "instance-state-name", "Values": schedulable_states},
+ {"Name": "tag-key", "Values": [self._scheduler_tag_key]},
+ ]
+ instances: Final[list[Instance]] = []
+ for page in paginator.paginate(Filters=filters):
+ for reservation in page["Reservations"]:
+ for instance in reservation["Instances"]:
+ instance_data = self._select_instance_data(
+ instance, schedules_with_hibernation
+ )
+ instances.append(instance_data)
+
+ self._logger.info(
+ 'Selected EC2 instance with ID {} in state "{}"',
+ instance_data["id"],
+ instance_data["state_name"],
+ )
+
+ self._logger.info(
+ "Quantity of EC2 instances in schedulable states: {}",
+ len(instances),
+ )
+
+ return instances
+
+ def _select_instance_data(
+ self, instance: InstanceTypeDef, schedules_with_hibernation: frozenset[str]
+ ) -> Instance:
+ tags: Final = get_tags(instance)
+ name: Final = tags.get("Name", "")
+ instance_id: Final = instance["InstanceId"]
+ state_code: Final = instance["State"]["Code"] & 0xFF
+ is_running: Final = state_code == EC2StateCode.RUNNING
+ is_terminated: Final = state_code == EC2StateCode.TERMINATED
+ schedule_name: Final = tags.get(self._scheduler_tag_key)
+
+ maintenance_window_schedule: InstanceSchedule | Literal[
+ "NOT-FOUND"
+ ] | None = None
+ schedule = None
+
+ if schedule_name is not None:
+ schedule = self._scheduling_context.schedules.get(schedule_name)
+ if (
+ schedule is not None
+ and schedule.use_maintenance_window
+ and schedule.ssm_maintenance_window
+ ):
+ maintenance_window_schedule = self._maintenance_window_schedules.get(
+ schedule.ssm_maintenance_window, None
+ )
+ if maintenance_window_schedule is None:
+ self._logger.error(
+ (
+ "SSM maintenance window {} used in schedule {} not found or "
+ "disabled"
+ ),
+ schedule.ssm_maintenance_window,
+ schedule.name,
+ )
+ self._maintenance_window_schedules[
+ schedule.ssm_maintenance_window
+ ] = "NOT-FOUND"
+ if maintenance_window_schedule == "NOT-FOUND":
+ maintenance_window_schedule = None
+
+ return Instance(
+ id=instance_id,
+ schedule_name=schedule_name,
+ hibernate=schedule_name in schedules_with_hibernation,
+ name=name,
+ state=state_code,
+ state_name=instance["State"]["Name"],
+ allow_resize=self.allow_resize,
+ resized=False,
+ is_running=is_running,
+ is_terminated=is_terminated,
+ current_state="running" if is_running else "stopped",
+ instancetype=instance["InstanceType"],
+ tags=tags,
+ maintenance_window=maintenance_window_schedule,
+ )
+
+ def resize_instance(self, instance: Instance, instance_type: str) -> None:
+ """
+ change the instance type of the EC2 instance with ID in `instance` to
+ `instance_type`
+ """
+ self._logger.info(
+ "Setting size for ec2 instance {} to {}", instance["id"], instance_type
+ )
+
+ try:
+ self._ec2.modify_instance_attribute(
+ InstanceId=instance["id"], InstanceType={"Value": instance_type}
+ )
+ except Exception as ex:
+ self._logger.error(
+ "Error resizing instance {}, ({})", instance["id"], str(ex)
+ )
+
+ def stop_instances(
+ self, instances_to_stop: list[Instance]
+ ) -> Iterator[tuple[str, ScheduleState]]:
+ """
+ stop EC2 instances with IDs in `instances_to_stop`
+
+ hibernate instances tagged with schedules that have been configured for
+ hibernate
+
+ tag instances that were successfully stopped with the stop tag keys and values
+ configured at a stack value, and remove start tag keys from the same instances
+ """
+ instance_ids_to_hibernate: Final[list[str]] = []
+ instance_ids_to_stop: Final[list[str]] = []
+
+ for instance in instances_to_stop:
+ # instances that are stopped for resizing cannot be hibernated
+ if instance["hibernate"] and instance["resized"]:
+ self._logger.info(
+ (
+ "EC2 instance with ID {} will not be hibernated because it "
+ "must be stopped for resize"
+ ),
+ instance["id"],
+ )
+
+ if instance["hibernate"] and not instance["resized"]:
+ instance_ids_to_hibernate.append(instance["id"])
+ else:
+ instance_ids_to_stop.append(instance["id"])
+
+ hibernate_responses = bisect_retry(
+ instance_ids_to_hibernate,
+ lambda ids: self._ec2.stop_instances(InstanceIds=ids, Hibernate=True),
+ )
+
+ stop_responses = bisect_retry(
+ instance_ids_to_stop, lambda ids: self._ec2.stop_instances(InstanceIds=ids)
+ )
+
+ stopping_instance_ids: Final[list[str]] = []
+
+ for response in chain(hibernate_responses, stop_responses):
+ if isinstance(response, FailureResponse):
+ self._logger.error(
+ "Failed to stop EC2 instance with ID {}: {}",
+ response.failed_input,
+ str(response.error),
+ )
+ else:
+ stopping_instance_ids.extend(
+ instance["InstanceId"] for instance in response["StoppingInstances"]
+ )
+
+ self._tag_instances(
+ stopping_instance_ids,
+ tag_templates_to_add=self._scheduling_context.stopped_tags,
+ tag_templates_to_remove=self._scheduling_context.started_tags,
+ )
+
+ yield from ((instance_id, "stopped") for instance_id in stopping_instance_ids)
+
+ def start_instances(
+ self, instances_to_start: list[Instance]
+ ) -> Iterator[tuple[str, ScheduleState]]:
+ """
+ start the EC2 instances with IDs in `instances_to_start`
+
+ tag instances that were successfully started with the start tag keys and values
+ configured at a stack value, and remove stop tag keys from the same instances
+ """
+ instance_ids = [instance["id"] for instance in instances_to_start]
+ responses: Final = bisect_retry(
+ instance_ids, lambda ids: self._ec2.start_instances(InstanceIds=ids)
+ )
+ starting_instance_ids: Final[list[str]] = []
+ for response in responses:
+ if isinstance(response, FailureResponse):
+ self._logger.error(
+ "Failed to start EC2 instance with ID {}: {}",
+ response.failed_input,
+ str(response.error),
+ )
+ else:
+ starting_instance_ids.extend(
+ instance["InstanceId"] for instance in response["StartingInstances"]
+ )
+
+ self._tag_instances(
+ starting_instance_ids,
+ tag_templates_to_add=self._scheduling_context.started_tags,
+ tag_templates_to_remove=self._scheduling_context.stopped_tags,
+ )
+
+ yield from ((instance_id, "running") for instance_id in starting_instance_ids)
+
+ def _tag_instances(
+ self,
+ instance_ids: list[str],
+ *,
+ tag_templates_to_add: list[TagTemplate],
+ tag_templates_to_remove: list[TagTemplate],
+ ) -> None:
+ """
+ add tags with keys and values in `tag_templates_to_add` to EC2 instances with
+ IDs in `instance_ids`, and remove tag keys in `tag_templates_to_remove` from the
+ same instances
+
+ tag keys that appear in both lists are updated with the values in
+ `tag_templates_to_add`
+ """
+ if not instance_ids:
+ return
+
+ tags_to_add: Final[list[TagTypeDef]] = [
+ {"Key": tag["Key"], "Value": tag["Value"]} for tag in tag_templates_to_add
+ ]
+ tag_keys_to_add: Final = frozenset(tag["Key"] for tag in tags_to_add)
+ tag_keys_to_remove: Final[list[TagTypeDef]] = [
+ {"Key": tag["Key"]}
+ for tag in tag_templates_to_remove
+ if tag["Key"] not in tag_keys_to_add
+ ]
+
+ if tag_keys_to_remove:
+ self._logger.info(
+ "Removing tags with keys {} from instances with IDs {}",
+ ", ".join(tag["Key"] for tag in tag_keys_to_remove),
+ ", ".join(instance_ids),
+ )
+ try:
+ self._ec2.delete_tags(Resources=instance_ids, Tags=tag_keys_to_remove)
+ except Exception as err:
+ self._logger.error(
+ "Error removing tags for instances with IDs {}: {}",
+ ", ".join(instance_ids),
+ str(err),
+ )
+ if tags_to_add:
+ self._logger.info(
+ "Adding tags {} to instances with IDs {}",
+ str(tags_to_add),
+ ", ".join(instance_ids),
+ )
+ try:
+ self._ec2.create_tags(Resources=instance_ids, Tags=tags_to_add)
+ except Exception as err:
+ self._logger.error(
+ "Error adding tags for instances with IDs {}: {}",
+ ", ".join(instance_ids),
+ str(err),
+ )
diff --git a/source/app/instance_scheduler/schedulers/rds_service.py b/source/app/instance_scheduler/service/rds.py
similarity index 63%
rename from source/app/instance_scheduler/schedulers/rds_service.py
rename to source/app/instance_scheduler/service/rds.py
index cb42ac96..3df2e3a7 100644
--- a/source/app/instance_scheduler/schedulers/rds_service.py
+++ b/source/app/instance_scheduler/service/rds.py
@@ -1,23 +1,52 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-
-import copy
import re
+from collections.abc import Callable, Iterator, Sequence
+from typing import TYPE_CHECKING, Any, Final, Literal, Optional
-from instance_scheduler import schedulers
-import re
-import copy
-
+from instance_scheduler import ScheduleState
from instance_scheduler.boto_retry import get_client_with_standard_retry
-from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler.configuration.instance_schedule import (
+ Instance,
+ InstanceSchedule,
+)
from instance_scheduler.configuration.running_period import RunningPeriod
+from instance_scheduler.configuration.running_period_dict_element import (
+ RunningPeriodDictElement,
+)
from instance_scheduler.configuration.scheduler_config_builder import (
SchedulerConfigBuilder,
)
+from instance_scheduler.configuration.scheduling_context import TagTemplate
from instance_scheduler.configuration.setbuilders.weekday_setbuilder import (
WeekdaySetBuilder,
)
+from instance_scheduler.service import Service, ServiceArgs
+
+if TYPE_CHECKING:
+ from mypy_boto3_rds.client import RDSClient
+ from mypy_boto3_rds.type_defs import (
+ DBClusterTypeDef,
+ DBInstanceTypeDef,
+ DescribeDBClustersMessageRequestTypeDef,
+ DescribeDBInstancesMessageRequestTypeDef,
+ TagTypeDef,
+ )
+ from mypy_boto3_resourcegroupstaggingapi.client import (
+ ResourceGroupsTaggingAPIClient,
+ )
+ from mypy_boto3_resourcegroupstaggingapi.type_defs import (
+ GetResourcesInputRequestTypeDef,
+ )
+else:
+ RDSClient = object
+ DBClusterTypeDef = object
+ DBInstanceTypeDef = object
+ DescribeDBClustersMessageRequestTypeDef = object
+ DescribeDBInstancesMessageRequestTypeDef = object
+ TagTypeDef = object
+ ResourceGroupsTaggingAPIClient = object
+ GetResourcesInputRequestTypeDef = object
RESTRICTED_RDS_TAG_VALUE_SET_CHARACTERS = r"[^a-zA-Z0-9\s_\.:+/=\\@-]"
@@ -55,51 +84,45 @@
MAINTENANCE_PERIOD_NAME = "RDS preferred Maintenance Window Period"
-class RdsService:
+class RdsService(Service[Instance]):
RDS_STATE_AVAILABLE = "available"
RDS_STATE_STOPPED = "stopped"
RDS_SCHEDULABLE_STATES = {RDS_STATE_AVAILABLE, RDS_STATE_STOPPED}
- def __init__(self):
- self.service_name = "rds"
- self.allow_resize = False
- self._instance_tags = None
-
- self._context = None
- self._session = None
- self._region = None
- self._account = None
- self._logger = None
- self._tagname = None
- self._stack_name = None
- self._config = None
-
- def _init_scheduler(self, args):
- """
- Initializes common parameters
- :param args: action parameters
- :return:
- """
- self._account = args.get(schedulers.PARAM_ACCOUNT)
- self._context = args.get(schedulers.PARAM_CONTEXT)
- self._logger = args.get(schedulers.PARAM_LOGGER)
- self._region = args.get(schedulers.PARAM_REGION)
- self._stack_name = args.get(schedulers.PARAM_STACK)
- self._session = args.get(schedulers.PARAM_SESSION)
- self._tagname = args.get(schedulers.PARAM_CONFIG).tag_name
- self._config = args.get(schedulers.PARAM_CONFIG)
- self._instance_tags = None
+ def __init__(self, args: ServiceArgs) -> None:
+ Service.__init__(self, args)
+
+ self._session: Final = args["session"]
+ self._region: Final = self._session.region_name
+ self._account: Final = args["account_id"]
+ self._logger: Final = args["logger"]
+ self._scheduling_context: Final = args["scheduling_context"]
+ self._scheduler_tag_key: Final = self._scheduling_context.tag_name
+ self._stack_name: Final = args["stack_name"]
+
+ self._instance_tags: Optional[dict[str, dict[str, str]]] = None
+
+ @property
+ def service_name(self) -> str:
+ return "rds"
+
+ @property
+ def allow_resize(self) -> bool:
+ return False
@property
- def rds_resource_tags(self):
+ def rds_resource_tags(self) -> dict[str, dict[str, str]]:
if self._instance_tags is None:
- tag_client = get_client_with_standard_retry(
+ tag_client: ResourceGroupsTaggingAPIClient = get_client_with_standard_retry(
"resourcegroupstaggingapi", session=self._session, region=self._region
)
- args = {
- "TagFilters": [{"Key": self._tagname}],
+ if self._scheduler_tag_key is None:
+ raise ValueError("RDS scheduler not initialized properly")
+
+ args: GetResourcesInputRequestTypeDef = {
+ "TagFilters": [{"Key": self._scheduler_tag_key}],
"ResourcesPerPage": 50,
"ResourceTypeFilters": ["rds:db", "rds:cluster"],
}
@@ -113,7 +136,7 @@ def rds_resource_tags(self):
self._instance_tags[resource["ResourceARN"]] = {
tag["Key"]: tag["Value"]
for tag in resource.get("Tags", {})
- if tag["Key"] in ["Name", self._tagname]
+ if tag["Key"] in ["Name", self._scheduler_tag_key]
}
if resp.get("PaginationToken", "") != "":
@@ -124,7 +147,7 @@ def rds_resource_tags(self):
return self._instance_tags
@staticmethod
- def build_schedule_from_maintenance_window(period_str):
+ def build_schedule_from_maintenance_window(period_str: str) -> InstanceSchedule:
"""
Builds a Instance running schedule based on an RDS preferred maintenance windows string in format ddd:hh:mm-ddd:hh:mm
:param period_str: rds maintenance windows string
@@ -145,7 +168,7 @@ def build_schedule_from_maintenance_window(period_str):
# windows with now day overlap, can do with one period for schedule
if start_day_string == stop_day_string:
- periods = [
+ periods: list[RunningPeriodDictElement] = [
{
"period": RunningPeriod(
name=MAINTENANCE_PERIOD_NAME,
@@ -185,20 +208,24 @@ def build_schedule_from_maintenance_window(period_str):
schedule = InstanceSchedule(
name=MAINTENANCE_SCHEDULE_NAME,
periods=periods,
- timezone="UTC",
+ timezone="UTC", # todo: is this even correct?
enforced=True,
)
return schedule
- def get_schedulable_resources(self, fn_is_schedulable, fn_describe_name, kwargs):
- self._init_scheduler(kwargs)
-
- client = get_client_with_standard_retry(
+ def get_schedulable_resources(
+ self,
+ fn_is_schedulable: Callable[[Any], bool],
+ fn_describe_name: Literal["describe_db_instances", "describe_db_clusters"],
+ ) -> list[Instance]:
+ client: RDSClient = get_client_with_standard_retry(
"rds", session=self._session, region=self._region
)
- describe_arguments = {}
+ describe_arguments: DescribeDBInstancesMessageRequestTypeDef | DescribeDBClustersMessageRequestTypeDef = (
+ {}
+ )
resource_name = fn_describe_name.split("_")[-1]
resource_name = resource_name[0].upper() + resource_name[1:]
resources = []
@@ -223,12 +250,12 @@ def get_schedulable_resources(self, fn_is_schedulable, fn_describe_name, kwargs)
rds_resource=resource, is_cluster=resource_name == "Clusters"
)
- schedule_name = resource_data[schedulers.INST_SCHEDULE]
+ schedule_name = resource_data["schedule_name"]
if schedule_name not in [None, ""]:
self._logger.debug(
DEBUG_SELECTED,
- resource_data[schedulers.INST_ID],
- resource_data[schedulers.INST_STATE_NAME],
+ resource_data["id"],
+ resource_data["state_name"],
schedule_name,
)
resources.append(resource_data)
@@ -236,7 +263,7 @@ def get_schedulable_resources(self, fn_is_schedulable, fn_describe_name, kwargs)
self._logger.debug(
DEBUG_WITHOUT_SCHEDULE,
resource_name[:-1],
- resource_data[schedulers.INST_ID],
+ resource_data["id"],
)
if "Marker" in rds_resp:
describe_arguments["Marker"] = rds_resp["Marker"]
@@ -247,8 +274,8 @@ def get_schedulable_resources(self, fn_is_schedulable, fn_describe_name, kwargs)
)
return resources
- def get_schedulable_rds_instances(self, kwargs):
- def is_schedulable_instance(rds_inst):
+ def get_schedulable_rds_instances(self) -> list[Instance]:
+ def is_schedulable_instance(rds_inst: DBInstanceTypeDef) -> bool:
db_id = rds_inst["DBInstanceIdentifier"]
state = rds_inst["DBInstanceStatus"]
@@ -273,11 +300,13 @@ def is_schedulable_instance(rds_inst):
)
return False
- if rds_inst["Engine"] in ["aurora"]:
+ if rds_inst["Engine"] in {"aurora", "aurora-mysql", "aurora-postgresql"}:
return False
if self.rds_resource_tags.get(rds_inst["DBInstanceArn"]) is None:
- self._logger.debug(DEBUG_NO_SCHEDULE_TAG, rds_inst, self._tagname)
+ self._logger.debug(
+ DEBUG_NO_SCHEDULE_TAG, rds_inst, self._scheduler_tag_key
+ )
return False
return True
@@ -285,11 +314,10 @@ def is_schedulable_instance(rds_inst):
return self.get_schedulable_resources(
fn_is_schedulable=is_schedulable_instance,
fn_describe_name="describe_db_instances",
- kwargs=kwargs,
)
- def get_schedulable_rds_clusters(self, kwargs):
- def is_schedulable(cluster_inst):
+ def get_schedulable_rds_clusters(self) -> list[Instance]:
+ def is_schedulable(cluster_inst: DBClusterTypeDef) -> bool:
db_id = cluster_inst["DBClusterIdentifier"]
state = cluster_inst["Status"]
@@ -299,7 +327,9 @@ def is_schedulable(cluster_inst):
return False
if self.rds_resource_tags.get(cluster_inst["DBClusterArn"]) is None:
- self._logger.debug(DEBUG_NO_SCHEDULE_TAG, cluster_inst, self._tagname)
+ self._logger.debug(
+ DEBUG_NO_SCHEDULE_TAG, cluster_inst, self._scheduler_tag_key
+ )
return False
return True
@@ -307,16 +337,15 @@ def is_schedulable(cluster_inst):
return self.get_schedulable_resources(
fn_is_schedulable=is_schedulable,
fn_describe_name="describe_db_clusters",
- kwargs=kwargs,
)
- def get_schedulable_instances(self, kwargs):
- instances = self.get_schedulable_rds_instances(kwargs)
- if self._config.schedule_clusters:
- instances += self.get_schedulable_rds_clusters(kwargs)
+ def get_schedulable_instances(self) -> list[Instance]:
+ instances = self.get_schedulable_rds_instances()
+ if self._scheduling_context.schedule_clusters:
+ instances += self.get_schedulable_rds_clusters()
return instances
- def _select_resource_data(self, rds_resource, is_cluster):
+ def _select_resource_data(self, rds_resource: Any, is_cluster: bool) -> Instance:
arn_for_tags = (
rds_resource["DBInstanceArn"]
if not is_cluster
@@ -332,52 +361,55 @@ def _select_resource_data(self, rds_resource, is_cluster):
is_running = state == self.RDS_STATE_AVAILABLE
- instance_data = {
- schedulers.INST_ID: rds_resource["DBInstanceIdentifier"]
+ if self._scheduler_tag_key is None:
+ raise ValueError("RDS scheduler not initialized properly")
+
+ instance_data = Instance(
+ id=rds_resource["DBInstanceIdentifier"]
if not is_cluster
else rds_resource["DBClusterIdentifier"],
- schedulers.INST_ARN: rds_resource["DBInstanceArn"]
+ arn=rds_resource["DBInstanceArn"]
if not is_cluster
else rds_resource["DBClusterArn"],
- schedulers.INST_ALLOW_RESIZE: self.allow_resize,
- schedulers.INST_HIBERNATE: False,
- schedulers.INST_STATE: state,
- schedulers.INST_STATE_NAME: state,
- schedulers.INST_IS_RUNNING: is_running,
- schedulers.INST_IS_TERMINATED: False,
- schedulers.INST_CURRENT_STATE: InstanceSchedule.STATE_RUNNING
- if is_running
- else InstanceSchedule.STATE_STOPPED,
- schedulers.INST_INSTANCE_TYPE: rds_resource["DBInstanceClass"]
+ allow_resize=self.allow_resize,
+ hibernate=False,
+ state=state,
+ state_name=state,
+ is_running=is_running,
+ is_terminated=False,
+ current_state="running" if is_running else "stopped",
+ instancetype=rds_resource["DBInstanceClass"]
if not is_cluster
else "cluster",
- schedulers.INST_ENGINE_TYPE: rds_resource["Engine"],
- schedulers.INST_MAINTENANCE_WINDOW: RdsService.build_schedule_from_maintenance_window(
+ engine_type=rds_resource["Engine"],
+ maintenance_window=RdsService.build_schedule_from_maintenance_window(
rds_resource["PreferredMaintenanceWindow"]
),
- schedulers.INST_TAGS: tags,
- schedulers.INST_NAME: tags.get("Name", ""),
- schedulers.INST_SCHEDULE: tags.get(self._tagname, None),
- schedulers.INST_DB_IS_CLUSTER: is_cluster,
- }
+ tags=tags,
+ name=tags.get("Name", ""),
+ schedule_name=tags.get(self._scheduler_tag_key, None),
+ is_cluster=is_cluster,
+ )
return instance_data
- def resize_instance(self, kwargs):
- pass
+ def resize_instance(self, _: Any, __: str) -> None:
+ """noop"""
- def _validate_rds_tag_values(self, tags):
- result = copy.deepcopy(tags)
- for t in result:
- original_value = t.get("Value", "")
+ def _validate_rds_tag_values(
+ self, tags: Sequence[TagTemplate]
+ ) -> Sequence[TagTypeDef]:
+ result: Final[list[TagTypeDef]] = []
+ for tag in tags:
+ original_value = tag.get("Value", "")
value = re.sub(RESTRICTED_RDS_TAG_VALUE_SET_CHARACTERS, " ", original_value)
value = value.replace("\n", " ")
if value != original_value:
- self._logger.warning(WARN_RDS_TAG_VALUE, original_value, t, value)
- t["Value"] = value
+ self._logger.warning(WARN_RDS_TAG_VALUE, original_value, tag, value)
+ result.append({"Key": tag["Key"], "Value": value})
return result
- def _stop_instance(self, client, inst):
- def does_snapshot_exist(name):
+ def _stop_instance(self, client: RDSClient, inst: Instance) -> None:
+ def does_snapshot_exist(name: str) -> bool:
try:
resp = client.describe_db_snapshots(
DBSnapshotIdentifier=name, SnapshotType="manual"
@@ -390,147 +422,145 @@ def does_snapshot_exist(name):
else:
raise ex
- args = {"DBInstanceIdentifier": inst.id}
+ args = {"DBInstanceIdentifier": inst["id"]}
- if self._config.create_rds_snapshot:
- snapshot_name = "{}-stopped-{}".format(self._stack_name, inst.id).replace(
- " ", ""
- )
+ if self._scheduling_context.create_rds_snapshot:
+ snapshot_name = "{}-stopped-{}".format(
+ self._stack_name, inst["id"]
+ ).replace(" ", "")
args["DBSnapshotIdentifier"] = snapshot_name
try:
if does_snapshot_exist(snapshot_name):
client.delete_db_snapshot(DBSnapshotIdentifier=snapshot_name)
self._logger.info(INF_DELETE_SNAPSHOT, snapshot_name)
- except Exception as ex:
+ except Exception:
self._logger.error(ERR_DELETING_SNAPSHOT, snapshot_name)
try:
client.stop_db_instance(**args)
- self._logger.info(INF_STOPPED_RESOURCE, "instance", inst.id)
+ self._logger.info(INF_STOPPED_RESOURCE, "instance", inst["id"])
except Exception as ex:
self._logger.error(
- ERR_STOPPING_INSTANCE, "instance", inst.instance_str, str(ex)
+ ERR_STOPPING_INSTANCE, "instance", inst["instance_str"], str(ex)
)
- def _tag_stopped_resource(self, client, rds_resource):
- stop_tags = self._validate_rds_tag_values(self._config.stopped_tags)
+ def _tag_stopped_resource(self, client: RDSClient, rds_resource: Instance) -> None:
+ stop_tags = self._validate_rds_tag_values(self._scheduling_context.stopped_tags)
if stop_tags is None:
stop_tags = []
stop_tags_key_names = [t["Key"] for t in stop_tags]
start_tags_keys = [
t["Key"]
- for t in self._config.started_tags
+ for t in self._scheduling_context.started_tags
if t["Key"] not in stop_tags_key_names
]
try:
- if start_tags_keys is not None and len(start_tags_keys):
+ if len(start_tags_keys):
self._logger.info(
INF_REMOVE_KEYS,
"start",
",".join(['"{}"'.format(k) for k in start_tags_keys]),
- rds_resource.arn,
+ rds_resource["arn"],
)
client.remove_tags_from_resource(
- ResourceName=rds_resource.arn, TagKeys=start_tags_keys
+ ResourceName=rds_resource["arn"], TagKeys=start_tags_keys
)
if len(stop_tags) > 0:
self._logger.info(
- INF_ADD_TAGS, "stop", str(stop_tags), rds_resource.arn
+ INF_ADD_TAGS, "stop", str(stop_tags), rds_resource["arn"]
)
client.add_tags_to_resource(
- ResourceName=rds_resource.arn, Tags=stop_tags
+ ResourceName=rds_resource["arn"], Tags=stop_tags
)
except Exception as ex:
- self._logger.warning(WARN_TAGGING_STOPPED, rds_resource.id, str(ex))
+ self._logger.warning(WARN_TAGGING_STOPPED, rds_resource["id"], str(ex))
- def _tag_started_instances(self, client, rds_resource):
- start_tags = self._validate_rds_tag_values(self._config.started_tags)
+ def _tag_started_instances(self, client: RDSClient, rds_resource: Instance) -> None:
+ start_tags = self._validate_rds_tag_values(
+ self._scheduling_context.started_tags
+ )
if start_tags is None:
start_tags = []
start_tags_key_names = [t["Key"] for t in start_tags]
stop_tags_keys = [
t["Key"]
- for t in self._config.stopped_tags
+ for t in self._scheduling_context.stopped_tags
if t["Key"] not in start_tags_key_names
]
try:
- if stop_tags_keys is not None and len(stop_tags_keys):
+ if len(stop_tags_keys):
self._logger.info(
INF_REMOVE_KEYS,
"stop",
",".join(['"{}"'.format(k) for k in stop_tags_keys]),
- rds_resource.arn,
+ rds_resource["arn"],
)
client.remove_tags_from_resource(
- ResourceName=rds_resource.arn, TagKeys=stop_tags_keys
+ ResourceName=rds_resource["arn"], TagKeys=stop_tags_keys
)
if start_tags is not None and len(start_tags) > 0:
self._logger.info(
- INF_ADD_TAGS, "start", str(start_tags), rds_resource.arn
+ INF_ADD_TAGS, "start", str(start_tags), rds_resource["arn"]
)
client.add_tags_to_resource(
- ResourceName=rds_resource.arn, Tags=start_tags
+ ResourceName=rds_resource["arn"], Tags=start_tags
)
except Exception as ex:
- self._logger.warning(WARN_TAGGING_STARTED, rds_resource.id, str(ex))
-
- # noinspection PyMethodMayBeStatic
- def stop_instances(self, kwargs):
- self._init_scheduler(kwargs)
+ self._logger.warning(WARN_TAGGING_STARTED, rds_resource["id"], str(ex))
+ def stop_instances(
+ self, instances_to_stop: list[Instance]
+ ) -> Iterator[tuple[str, ScheduleState]]:
client = get_client_with_standard_retry(
"rds", session=self._session, region=self._region
)
- stopped_instances = kwargs["stopped_instances"]
-
- for rds_resource in stopped_instances:
+ for rds_resource in instances_to_stop:
try:
- if rds_resource.is_cluster:
- client.stop_db_cluster(DBClusterIdentifier=rds_resource.id)
- self._logger.info(INF_STOPPED_RESOURCE, "cluster", rds_resource.id)
+ if rds_resource["is_cluster"]:
+ client.stop_db_cluster(DBClusterIdentifier=rds_resource["id"])
+ self._logger.info(
+ INF_STOPPED_RESOURCE, "cluster", rds_resource["id"]
+ )
else:
self._stop_instance(client, rds_resource)
self._tag_stopped_resource(client, rds_resource)
- yield rds_resource.id, InstanceSchedule.STATE_STOPPED
+ yield rds_resource["id"], "stopped"
except Exception as ex:
self._logger.error(
ERR_STOPPING_INSTANCE,
- "cluster" if rds_resource.is_cluster else "instance",
- rds_resource.instance_str,
+ "cluster" if rds_resource["is_cluster"] else "instance",
+ rds_resource["instance_str"],
str(ex),
)
- # noinspection PyMethodMayBeStatic
- def start_instances(self, kwargs):
- self._init_scheduler(kwargs)
-
- client = get_client_with_standard_retry(
+ def start_instances(
+ self, instances_to_start: list[Instance]
+ ) -> Iterator[tuple[str, ScheduleState]]:
+ client: RDSClient = get_client_with_standard_retry(
"rds", session=self._session, region=self._region
)
- started_instances = kwargs["started_instances"]
- for rds_resource in started_instances:
+ for rds_resource in instances_to_start:
try:
- if rds_resource.is_cluster:
- client.start_db_cluster(DBClusterIdentifier=rds_resource.id)
+ if rds_resource["is_cluster"]:
+ client.start_db_cluster(DBClusterIdentifier=rds_resource["id"])
else:
- client.start_db_instance(DBInstanceIdentifier=rds_resource.id)
+ client.start_db_instance(DBInstanceIdentifier=rds_resource["id"])
self._tag_started_instances(client, rds_resource)
- yield rds_resource.id, InstanceSchedule.STATE_RUNNING
+ yield rds_resource["id"], "running"
except Exception as ex:
self._logger.error(
ERR_STARTING_INSTANCE,
- "cluster" if rds_resource.is_cluster else "instance",
- rds_resource.instance_str,
+ "cluster" if rds_resource["is_cluster"] else "instance",
+ rds_resource["instance_str"],
str(ex),
)
- return
diff --git a/source/app/instance_scheduler/util/__init__.py b/source/app/instance_scheduler/util/__init__.py
index e1ef0eea..02f5ade9 100644
--- a/source/app/instance_scheduler/util/__init__.py
+++ b/source/app/instance_scheduler/util/__init__.py
@@ -1,49 +1,27 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
+import json as _json
+from typing import Any as _Any
+from botocore.config import Config as _Config
-import json
+from instance_scheduler.util.app_env import get_app_env as _get_app_env
+from instance_scheduler.util.custom_encoder import CustomEncoder as _CustomEncoder
-from instance_scheduler.util.custom_encoder import CustomEncoder
-import botocore
-import os
-ENV_METRICS_URL = "METRICS_URL"
-# Solution ID
-ENV_SOLUTION_ID = "SOLUTION_ID"
-# Send metrics flag
-ENV_SEND_METRICS = "SEND_METRICS"
-# STACK_ID
-STACK_ID = "STACK_ID"
-# UUID_KEY
-UUID_KEY = "UUID_KEY"
-USER_AGENT_EXTRA = "USER_AGENT_EXTRA"
-
-
-def safe_json(d, indent=0):
+def safe_json(d: _Any, indent: int = 0) -> str:
"""
Returns a json document, using a custom encoder that converts all data types not supported by json
:param d: input dictionary
:param indent: indent level for output document
:return: json document for input dictionary
"""
- return json.dumps(d, cls=CustomEncoder, indent=indent)
-
-
-def as_bool(b):
- s = str(b).lower()
- if s == "true":
- return True
- if s == "false":
- return False
- return None
+ return _json.dumps(d, cls=_CustomEncoder, indent=indent)
-def get_config():
- # TODO move the user agent string to lambda environment and make it configurable from deployment.
- user_agent_extra_string = os.getenv("USER_AGENT_EXTRA", "AwsSolution/SO0030/v1.5.0")
- solution_config = {
- "user_agent_extra": user_agent_extra_string,
- "retries": {"max_attempts": 5, "mode": "standard"},
- }
- return botocore.config.Config(**solution_config)
+def get_boto_config() -> _Config:
+ """Returns a boto3 config with standard retries and `user_agent_extra`"""
+ return _Config(
+ retries={"max_attempts": 5, "mode": "standard"},
+ user_agent_extra=_get_app_env().user_agent_extra,
+ )
diff --git a/source/app/instance_scheduler/util/app_env.py b/source/app/instance_scheduler/util/app_env.py
new file mode 100644
index 00000000..e570a304
--- /dev/null
+++ b/source/app/instance_scheduler/util/app_env.py
@@ -0,0 +1,138 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from dataclasses import dataclass
+from os import environ
+from typing import Optional
+from zoneinfo import ZoneInfo, ZoneInfoNotFoundError
+
+
+@dataclass(frozen=True)
+class AppEnv:
+ scheduler_frequency_minutes: int
+ log_group: str
+ topic_arn: str
+ stack_name: str
+ send_anonymous_metrics: bool
+ solution_id: str
+ solution_version: str
+ enable_debug_logging: bool
+ user_agent_extra: str
+ anonymous_metrics_url: str
+ stack_id: str
+ uuid_key: str
+ start_ec2_batch_size: int
+ schedule_tag_key: str
+ default_timezone: ZoneInfo
+ enable_cloudwatch_metrics: bool
+ enable_ec2_service: bool
+ enable_rds_service: bool
+ enable_rds_clusters: bool
+ enable_rds_snapshots: bool
+ schedule_regions: list[str]
+ app_namespace: str
+ scheduler_role_name: str
+ enable_schedule_hub_account: bool
+ enable_ec2_ssm_maintenance_windows: bool
+ start_tags: list[str]
+ stop_tags: list[str]
+ enable_aws_organizations: bool
+ maintenance_window_table_name: str
+ config_table_name: str
+ state_table_name: str
+
+ def scheduled_services(self) -> list[str]:
+ result = []
+ if self.enable_ec2_service:
+ result.append("ec2")
+ if self.enable_rds_service:
+ result.append("rds")
+ return result
+
+
+# cache the application environment for warm starts
+_app_env: Optional[AppEnv] = None
+
+
+def get_app_env() -> AppEnv:
+ """
+ Retrieve the current application environment. This function should be called once
+ per Lambda execution.
+
+ Do not pass around the environment object. Do not retrieve the environment object
+ whenever a environment setting is needed. Do not retrieve settings directly from the
+ environment except where required for initialization order reasons.
+
+ Most classes only need a small number of environment settings. The top-level Lambda
+ handler should pass the needed values to the constructor for that class. This allows
+ lower-level classes to remain testable with only the options they require rather
+ than every option required by the entire system. It also prevents the environment
+ class from becoming bloated with other runtime information.
+ """
+ global _app_env
+ if not _app_env:
+ _app_env = _from_environment()
+ return _app_env
+
+
+class AppEnvError(RuntimeError):
+ pass
+
+
+def _from_environment() -> AppEnv:
+ try:
+ return AppEnv(
+ scheduler_frequency_minutes=int(environ["SCHEDULER_FREQUENCY"]),
+ log_group=environ["LOG_GROUP"],
+ topic_arn=environ["ISSUES_TOPIC_ARN"],
+ stack_name=environ["STACK_NAME"],
+ send_anonymous_metrics=_to_bool(environ["SEND_METRICS"]),
+ solution_id=environ["SOLUTION_ID"],
+ solution_version=environ["SOLUTION_VERSION"],
+ enable_debug_logging=_to_bool(environ["TRACE"]),
+ user_agent_extra=environ["USER_AGENT_EXTRA"],
+ anonymous_metrics_url=environ["METRICS_URL"],
+ stack_id=environ["STACK_ID"],
+ uuid_key=environ["UUID_KEY"],
+ start_ec2_batch_size=int(environ["START_EC2_BATCH_SIZE"]),
+ schedule_tag_key=environ["SCHEDULE_TAG_KEY"],
+ default_timezone=ZoneInfo(environ["DEFAULT_TIMEZONE"]),
+ enable_cloudwatch_metrics=_to_bool(environ["ENABLE_CLOUDWATCH_METRICS"]),
+ enable_ec2_service=_to_bool(environ["ENABLE_EC2_SERVICE"]),
+ enable_rds_service=_to_bool(environ["ENABLE_RDS_SERVICE"]),
+ enable_rds_clusters=_to_bool(environ["ENABLE_RDS_CLUSTERS"]),
+ enable_rds_snapshots=_to_bool(environ["ENABLE_RDS_SNAPSHOTS"]),
+ schedule_regions=_to_list(environ["SCHEDULE_REGIONS"]),
+ app_namespace=environ["APP_NAMESPACE"],
+ scheduler_role_name=environ["SCHEDULER_ROLE_NAME"],
+ enable_schedule_hub_account=_to_bool(
+ environ["ENABLE_SCHEDULE_HUB_ACCOUNT"]
+ ),
+ enable_ec2_ssm_maintenance_windows=_to_bool(
+ environ["ENABLE_EC2_SSM_MAINTENANCE_WINDOWS"]
+ ),
+ start_tags=_to_list(environ["START_TAGS"]),
+ stop_tags=_to_list(environ["STOP_TAGS"]),
+ enable_aws_organizations=_to_bool(environ["ENABLE_AWS_ORGANIZATIONS"]),
+ maintenance_window_table_name=environ["MAINTENANCE_WINDOW_TABLE"],
+ config_table_name=environ["CONFIG_TABLE"],
+ state_table_name=environ["STATE_TABLE"],
+ )
+ except ZoneInfoNotFoundError as err:
+ raise AppEnvError(f"Invalid timezone: {err.args[0]}") from err
+ except KeyError as err:
+ raise AppEnvError(
+ f"Missing required application environment variable: {err.args[0]}"
+ ) from err
+
+
+def _to_bool(value: str) -> bool:
+ return value.strip().lower() in {"true", "yes"}
+
+
+def _to_list(value: str) -> list[str]:
+ items = []
+ for item in value.split(","):
+ stripped = item.strip()
+ if stripped:
+ items.append(stripped)
+ return items
diff --git a/source/app/instance_scheduler/util/batch.py b/source/app/instance_scheduler/util/batch.py
new file mode 100644
index 00000000..0aacb74b
--- /dev/null
+++ b/source/app/instance_scheduler/util/batch.py
@@ -0,0 +1,55 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from collections.abc import Callable
+from dataclasses import dataclass
+from typing import Final, Generic, TypeVar
+
+T = TypeVar("T")
+
+
+@dataclass
+class FailureResponse(Generic[T]):
+ failed_input: T
+ error: Exception
+
+
+U = TypeVar("U")
+
+
+def bisect_retry(
+ inputs: list[T], action: Callable[[list[T]], U]
+) -> list[U | FailureResponse[T]]:
+ """
+ Retry an action taking a list of inputs by successively splitting the inputs in half
+
+ When performing operations on a list of inputs that can fail due to any one of the
+ inputs being invalid, but with no way to know which input(s) caused the failure,
+ retry the operation on successively smaller inputs until it succeeds.
+
+ This function should minimize the number of actions taken when no inputs are
+ problematic, and it should minimize the number of calls needed for non-problematic
+ inputs to succeed.
+
+ Assume that actions with empty lists would be no-ops and skip them.
+
+ Assume that if the operation fails on a list of size one, that input is problematic
+ and will never result in a successful action. For this reason, `action` should
+ handle ephemeral errors.
+
+ Return a list of responses from successful actions. For actions that failed, return
+ a tuple of the single input item that resulted in an error and the error that was
+ raised.
+ """
+ if not inputs:
+ return []
+ try:
+ return [action(inputs)]
+ except Exception as err:
+ length: Final = len(inputs)
+ if length == 1:
+ return [FailureResponse(failed_input=inputs[0], error=err)]
+
+ midpoint: Final = length // 2
+ left: Final = bisect_retry(inputs[0:midpoint], action)
+ right: Final = bisect_retry(inputs[midpoint:], action)
+ return left + right
diff --git a/source/app/instance_scheduler/util/custom_encoder.py b/source/app/instance_scheduler/util/custom_encoder.py
index f2862777..b0fa57ec 100644
--- a/source/app/instance_scheduler/util/custom_encoder.py
+++ b/source/app/instance_scheduler/util/custom_encoder.py
@@ -1,10 +1,9 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-
import decimal
import json
from datetime import datetime
+from typing import Any
class CustomEncoder(json.JSONEncoder):
@@ -12,7 +11,7 @@ class CustomEncoder(json.JSONEncoder):
Internal class used for serialization of types not supported in json.
"""
- def default(self, o): # pylint: disable=E0202
+ def default(self, o: Any) -> Any:
# sets become lists
if isinstance(o, set):
return list(o)
diff --git a/source/app/instance_scheduler/util/custom_resource.py b/source/app/instance_scheduler/util/custom_resource.py
index e564c9db..69e07878 100644
--- a/source/app/instance_scheduler/util/custom_resource.py
+++ b/source/app/instance_scheduler/util/custom_resource.py
@@ -1,20 +1,48 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-
import json
import threading
import uuid
+from abc import ABC, abstractmethod
+from collections.abc import Mapping
+from typing import TYPE_CHECKING, Any, Generic, Literal, TypeGuard, TypeVar
import requests
+from typing_extensions import NotRequired, TypedDict
+
+from instance_scheduler.handler.base import Handler
+
+if TYPE_CHECKING:
+ from aws_lambda_powertools.utilities.typing import LambdaContext
+else:
+ LambdaContext = object
+
+ResourcePropertiesType = TypeVar("ResourcePropertiesType", bound=Mapping[str, Any])
-class CustomResource:
+class CustomResourceRequest(TypedDict, Generic[ResourcePropertiesType]):
+ ServiceToken: str # Lambda Function ARN
+ RequestType: Literal["Create", "Update", "Delete"]
+ ResponseURL: str # CloudFormation pre-signed URL
+ StackId: str # CloudFormation Stack ARN
+ RequestId: str # UUID
+ ResourceType: str
+ LogicalResourceId: str
+ PhysicalResourceId: str
+ ResourceProperties: ResourcePropertiesType
+ OldResourceProperties: NotRequired[ResourcePropertiesType]
+
+
+class CustomResource(
+ Generic[ResourcePropertiesType],
+ Handler[CustomResourceRequest[ResourcePropertiesType]],
+ ABC,
+):
EVENT_TYPE_CREATE = "Create"
EVENT_TYPE_UPDATE = "Update"
EVENT_TYPE_DELETE = "Delete"
- def __init__(self, event, context):
+ def __init__(self, event: Mapping[str, Any], context: LambdaContext) -> None:
self.event = event
self.context = context
# physical resource is empty for create request, for other requests is it the returned physical id from the create request
@@ -29,108 +57,108 @@ def __init__(self, event, context):
# Returned attributes of custom resource
@property
- def response_data(self):
+ def response_data(self) -> Any:
return self.response["Data"]
# Test if event is a request custom resource request from cloudformation
@staticmethod
- def is_handling_request(event):
+ def is_handling_request(
+ event: Mapping[str, Any]
+ ) -> TypeGuard[CustomResourceRequest[ResourcePropertiesType]]:
return event.get("StackId") is not None
# Returns Logical Resource Id in cloudformation stack
@property
- def logical_resource_id(self):
+ def logical_resource_id(self) -> Any:
return self.event.get("LogicalResourceId")
# Returns the id of the cloudformation request
@property
- def request_id(self):
+ def request_id(self) -> Any:
return self.event.get("RequestId")
# Returns the resource properties of the custom resource, these are used to pass data to te custom resource
@property
- def resource_properties(self):
+ def resource_properties(self) -> ResourcePropertiesType:
return self.event.get("ResourceProperties", {})
# Returns the previous resource properties of the custom resource, these are used to customize the updates
@property
- def old_resource_properties(self):
+ def old_resource_properties(self) -> ResourcePropertiesType:
return self.event.get("OldResourceProperties", {})
# Returns optional timeout
@property
- def timeout(self):
+ def timeout(self) -> Any:
return self.resource_properties.get("timeout", None)
# Returns the type of the custom resource
@property
- def resource_type(self):
+ def resource_type(self) -> Any:
return self.event.get("ResourceType")
# Returns the URL to send the response to cloudformation with the result of the request
@property
- def response_url(self):
+ def response_url(self) -> Any:
return self.event.get("ResponseURL")
# Returns the type of the request which can be one of the following: Create, Update, Delete
@property
- def request_type(self):
+ def request_type(self) -> Any:
return self.event.get("RequestType")
- # Returns the service token of the request
- @property
- def service_token(self):
- return self.event.get("ServiceToken")
-
# Returns the id of the stack
@property
- def stack_id(self):
+ def stack_id(self) -> Any:
return self.event.get("StackId")
# Returns the short name of the stack
@property
- def stack_name(self):
+ def stack_name(self) -> Any:
sid = self.stack_id
last = sid.split(":")[-1]
name = last.split("/")[-2]
return name
@property
- def region(self):
+ def region(self) -> Any:
return self.stack_id.split(":")[3]
# Build unique physical id
- def new_physical_resource_id(self):
+ def new_physical_resource_id(self) -> str:
uu = str(uuid.uuid4()).replace("-", "")[0:14]
new_id = "{}-{}-{}".format(self.__class__.__name__, self.stack_name, uu)
return new_id.lower()
# Handles Create request, overwrite in inherited class to implement create actions
# Return True on success, False if on failure
- def _create_request(self):
+ @abstractmethod
+ def _create_request(self) -> bool:
self.response["Reason"] = "No handler for Create request"
return True
# Handles Update request, overwrite in inherited class to implement update actions
# Return True on success, False if on failure
- def _update_request(self):
+ @abstractmethod
+ def _update_request(self) -> bool:
self.response["Reason"] = "No handler for Update request"
return True
# Handles Delete request, overwrite in inherited class to implement delete actions
# Return True on success, False if on failure
- def _delete_request(self):
+ @abstractmethod
+ def _delete_request(self) -> bool:
self.response["Reason"] = "No handler for Delete request"
return True
- def fn_timeout(self):
+ def fn_timeout(self) -> None:
print("Execution is about to time out, sending failure message")
self.response["Status"] = "FAILED"
self.response["Reason"] = "Timeout"
self._send_response()
# Handles cloudformation request
- def handle_request(self):
+ def handle_request(self) -> Any:
timeleft = (
(self.context.get_remaining_time_in_millis() / 1000.00) - 0.5
if self.context is not None
@@ -170,7 +198,7 @@ def handle_request(self):
return self._send_response()
# Send the response to cloudformation
- def _send_response(self):
+ def _send_response(self) -> bool:
# Build the PUT request and the response data
resp = json.dumps(self.response)
diff --git a/source/app/instance_scheduler/util/display_helper.py b/source/app/instance_scheduler/util/display_helper.py
index 0b152329..94830ea0 100644
--- a/source/app/instance_scheduler/util/display_helper.py
+++ b/source/app/instance_scheduler/util/display_helper.py
@@ -1,12 +1,14 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
+from collections.abc import Iterator
+from typing import Any
-def time_str(t):
+def time_str(t: Any) -> str:
return DisplayHelper.time_as_str(t)
-def set_str(the_set, displaynames=None, offset=0):
+def set_str(the_set: Any, displaynames: Any = None, offset: int = 0) -> str:
return DisplayHelper.set_as_str(
the_set=the_set, display_names=displaynames, offset=offset
)
@@ -17,12 +19,9 @@ class DisplayHelper:
Class that implements helper functions for displaying sets of data in a more readable form
"""
- def __init__(self):
- pass
-
# uniform string to display time
@staticmethod
- def time_as_str(t):
+ def time_as_str(t: Any) -> str:
"""
Returns the time in a standard format
:param t: time
@@ -31,7 +30,7 @@ def time_as_str(t):
return "{:0>2d}:{:0>2d}:{:0>2d}".format(t.hour, t.minute, t.second)
@staticmethod
- def set_as_str(the_set, display_names=None, offset=0):
+ def set_as_str(the_set: Any, display_names: Any = None, offset: int = 0) -> str:
"""
Displays a set as a readable string. Adjacent elements are combined in x-y ranges. A list of strings can be passed
to the set to map the values to text.
@@ -42,7 +41,7 @@ def set_as_str(the_set, display_names=None, offset=0):
"""
result = []
- def get_sub_sets():
+ def get_sub_sets() -> Iterator[set[Any]]:
if the_set is not None and len(the_set) > 0:
temp = sorted(the_set)
last = temp[0]
diff --git a/source/app/instance_scheduler/util/dynamodb_utils.py b/source/app/instance_scheduler/util/dynamodb_utils.py
index 18358dcf..cc3d7f60 100644
--- a/source/app/instance_scheduler/util/dynamodb_utils.py
+++ b/source/app/instance_scheduler/util/dynamodb_utils.py
@@ -1,12 +1,23 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
+from typing import TYPE_CHECKING, Any
import boto3
-from instance_scheduler import util
+
+from instance_scheduler.util import get_boto_config
+
+if TYPE_CHECKING:
+ from mypy_boto3_dynamodb.service_resource import Table
+else:
+ Table = object
class DynamoDBUtils:
@staticmethod
- def get_dynamodb_table_resource_ref(table_name):
- return boto3.resource("dynamodb", config=util.get_config()).Table(table_name)
+ def get_dynamodb_table_resource_ref(
+ table_name: str,
+ ) -> Any: # todo: switch typing to "Table"
+ table: Table = boto3.resource("dynamodb", config=get_boto_config()).Table(
+ table_name
+ )
+ return table
diff --git a/source/app/instance_scheduler/util/logger.py b/source/app/instance_scheduler/util/logger.py
index 8a443f38..cb1c2cf9 100644
--- a/source/app/instance_scheduler/util/logger.py
+++ b/source/app/instance_scheduler/util/logger.py
@@ -1,88 +1,64 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-
-import os
import time
-from datetime import datetime
+from types import TracebackType
+from typing import TYPE_CHECKING, Any, Optional
from instance_scheduler import boto_retry
-LOG_FORMAT = "{:7s} : {}"
-
-ENV_LOG_GROUP = "LOG_GROUP"
-ENV_ISSUES_TOPIC_ARN = "ISSUES_TOPIC_ARN"
-ENV_SUPPRESS_LOG_STDOUT = "SUPPRESS_LOG_TO_STDOUT"
-
-LOG_LEVEL_INFO = "INFO"
-LOG_LEVEL_ERROR = "ERROR"
-LOG_LEVEL_WARNING = "WARNING"
-LOG_LEVEL_DEBUG = "DEBUG"
+if TYPE_CHECKING:
+ from mypy_boto3_logs.client import CloudWatchLogsClient
+ from mypy_boto3_logs.type_defs import PutLogEventsRequestRequestTypeDef
+ from mypy_boto3_sns.client import SNSClient
+else:
+ CloudWatchLogsClient = object
+ SNSClient = object
+ PutLogEventsRequestRequestTypeDef = object
LOG_MAX_BATCH_SIZE = 1048576
LOG_ENTRY_ADDITIONAL = 26
class Logger:
- """
- Wrapper class for CloudWatch logging with buffering and helper methods
- """
-
- def __init__(self, logstream, context, loggroup=None, buffersize=10, debug=False):
- def get_loggroup(lambda_context):
- group = os.getenv(ENV_LOG_GROUP, None)
- if group is None:
- if lambda_context is None:
- return None
- group = lambda_context.log_group_name
- return group
-
- self._logstream = logstream
- self._buffer_size = min(buffersize, 10000)
- self._context = context
- self._buffer = []
+ def __init__(
+ self,
+ *,
+ log_group: str,
+ log_stream: str,
+ topic_arn: str,
+ debug: bool = False,
+ ) -> None:
+ self._log_group = log_group
+ self._log_stream = log_stream
+ self._topic_arn = topic_arn
self._debug = debug
+ self._buffer_size = 60 if self._debug else 30
+ self._buffer: list[tuple[int, str]] = []
self._cached_size = 0
- self._client = None
- self._log_sequence_token = None
- self._loggroup = (
- loggroup if loggroup is not None else get_loggroup(self._context)
- )
-
- self._sns = None
+ self._client: Optional[CloudWatchLogsClient] = None
+ self._sns: Optional[SNSClient] = None
- def __enter__(self):
- """
- Returns itself as the managed resource.
- :return:
- """
+ def __enter__(self) -> "Logger":
return self
- def __exit__(self, exc_type, exc_val, exc_tb):
- """
- Writes all cached action items to dynamodb table when going out of scope
- :param exc_type:
- :param exc_val:
- :param exc_tb:
- :return:
- """
+ def __exit__(
+ self,
+ exc_type: Optional[type[BaseException]],
+ exc_value: Optional[BaseException],
+ traceback: Optional[TracebackType],
+ ) -> None:
self.flush()
- def _emit(self, level, msg, *args):
+ def _emit(self, level: str, msg: str, *args: Any) -> str:
s = msg if len(args) == 0 else msg.format(*args)
t = time.time()
- s = LOG_FORMAT.format(level, s)
+ s = "{:7s} : {}".format(level, s)
if self._cached_size + (len(s) + LOG_ENTRY_ADDITIONAL) > LOG_MAX_BATCH_SIZE:
self.flush()
self._cached_size += len(s) + LOG_ENTRY_ADDITIONAL
- if (
- self._context is None
- and str(os.getenv(ENV_SUPPRESS_LOG_STDOUT, False)).lower() != "true"
- ):
- print("> " + s)
self._buffer.append((int(t * 1000), s))
if len(self._buffer) >= self._buffer_size:
@@ -91,72 +67,53 @@ def _emit(self, level, msg, *args):
return s
@property
- def debug_enabled(self):
- """
- Return debug on/off switch
- :return: debug on/of
- """
- return self._debug
-
- @property
- def sns(self):
+ def sns(self) -> SNSClient:
if self._sns is None:
self._sns = boto_retry.get_client_with_standard_retry("sns")
return self._sns
- @debug_enabled.setter
- def debug_enabled(self, value):
- """
- Sets debug switch
- :param value: True to enable debugging, False to disable
- :return:
- """
- self._debug = value
-
- def publish_to_sns(self, level, msg):
+ def publish_to_sns(self, level: str, msg: str) -> None:
"""
Publish message to sns topic
:param msg:
:param level:
:return:
"""
- sns_arn = os.getenv(ENV_ISSUES_TOPIC_ARN, None)
- if sns_arn is not None:
- message = "Loggroup: {}\nLogstream {}\n{} : {}".format(
- self._loggroup, self._logstream, level, msg
- )
- self.sns.publish(TopicArn=sns_arn, Message=message)
-
- def info(self, msg, *args):
+ message = "Loggroup: {}\nLogstream {}\n{} : {}".format(
+ self._log_group, self._log_stream, level, msg
+ )
+ self.sns.publish(TopicArn=self._topic_arn, Message=message)
+
+ def info(self, msg: str, *args: Any) -> None:
"""
Logs informational message
:param msg: Message format string
:param args: Message parameters
:return:
"""
- self._emit(LOG_LEVEL_INFO, msg, *args)
+ self._emit("INFO", msg, *args)
- def error(self, msg, *args):
+ def error(self, msg: str, *args: Any) -> None:
"""
Logs error message
:param msg: Error message format string
:param args: parameters
:return:
"""
- s = self._emit(LOG_LEVEL_ERROR, msg, *args)
+ s = self._emit("ERROR", msg, *args)
self.publish_to_sns("Error", s)
- def warning(self, msg, *args):
+ def warning(self, msg: str, *args: Any) -> None:
"""
Logs warning message
:param msg: Warning message format string
:param args: parameters
:return:
"""
- s = self._emit(LOG_LEVEL_WARNING, msg, *args)
+ s = self._emit("WARNING", msg, *args)
self.publish_to_sns("Warning", s)
- def debug(self, msg, *args):
+ def debug(self, msg: str, *args: Any) -> None:
"""
Conditionally logs debug message, does not log if debugging is disabled
:param msg: Debug message format string
@@ -164,23 +121,15 @@ def debug(self, msg, *args):
:return:
"""
if self._debug:
- self._emit(LOG_LEVEL_DEBUG, msg, *args)
-
- def clear(self):
- """
- Clear all buffered error messages
- :return:
- """
- self._buffer = []
+ self._emit("DEBUG", msg, *args)
@property
- def client(self):
+ def client(self) -> CloudWatchLogsClient:
if self._client is None:
- methods = ["create_log_stream"]
self._client = boto_retry.get_client_with_standard_retry("logs")
return self._client
- def flush(self):
+ def flush(self) -> None:
"""
Writes all buffered messages to CloudWatch Stream
:return:
@@ -189,9 +138,9 @@ def flush(self):
if len(self._buffer) == 0:
return
- put_event_args = {
- "logGroupName": self._loggroup,
- "logStreamName": self._logstream,
+ put_event_args: PutLogEventsRequestRequestTypeDef = {
+ "logGroupName": self._log_group,
+ "logStreamName": self._log_stream,
"logEvents": [{"timestamp": r[0], "message": r[1]} for r in self._buffer],
}
@@ -205,12 +154,7 @@ def flush(self):
except self.client.exceptions.ResourceNotFoundException:
retries -= 1
self.client.create_log_stream(
- logGroupName=self._loggroup, logStreamName=self._logstream
- )
- except self.client.exceptions.InvalidSequenceTokenException as ex:
- retries -= 1
- put_event_args["sequenceToken"] = ex.response.get(
- "expectedSequenceToken"
+ logGroupName=self._log_group, logStreamName=self._log_stream
)
except Exception:
return
diff --git a/source/app/instance_scheduler/util/metrics.py b/source/app/instance_scheduler/util/metrics.py
deleted file mode 100644
index 9e0e8888..00000000
--- a/source/app/instance_scheduler/util/metrics.py
+++ /dev/null
@@ -1,105 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-
-import os
-import uuid
-from datetime import datetime
-
-import requests
-
-
-from instance_scheduler import util
-from instance_scheduler.util import safe_json
-from instance_scheduler.version import VERSION
-import boto3
-
-# from botocore.exceptions import ClientError
-import botocore
-
-INF_METRICS_DATA = "Sending anonymous metrics data: {}"
-INF_METRICS_DATA_SENT = "Metrics data send, status code is {}, message is {}"
-WARN_ENV_METRICS_URL_NOT_SET = (
- "Environment variable {} is not set, metrics dat is not sent"
-)
-WARN_SENDING_METRICS_FAILED = "Failed send metrics data ({})"
-WARN_SOLUTION_ID_NOT_SET = "Solution id is not set, metrics are not sent"
-
-
-def allow_send_metrics():
- return str(os.getenv(util.ENV_SEND_METRICS, "false")).lower() == "true"
-
-
-def send_metrics_data(metrics, logger):
- """
- Sends metrics data
- :param metrics: metrics data
- :param logger: logger
- :return:
- """
- try:
- url = os.getenv(util.ENV_METRICS_URL, None)
- if url is None:
- logger.warning(WARN_ENV_METRICS_URL_NOT_SET, util.ENV_METRICS_URL)
- return
-
- solution_id = os.getenv(util.ENV_SOLUTION_ID, None)
- if solution_id is None:
- logger.warning(WARN_SOLUTION_ID_NOT_SET)
- return
- if solution_id is None:
- logger.warning(WARN_SOLUTION_ID_NOT_SET)
- return
-
- stackId = os.getenv(util.STACK_ID, None)[-36:]
- uuid_key = os.getenv(util.UUID_KEY) + str(stackId)
- user_agent_extra_string = os.getenv(util.USER_AGENT_EXTRA)
- try:
- if user_agent_extra_string is not None:
- solution_config = {"user_agent_extra": user_agent_extra_string}
- config = botocore.config.Config(**solution_config)
- else:
- config = None
-
- client = boto3.client("ssm", config=config)
- response = client.get_parameter(Name=uuid_key)
- uuid_parameter = response.get("Parameter", {}).get("Value")
- except botocore.exceptions.ClientError as ex:
- if ex.response.get("Error", {}).get("Code") == "ParameterNotFound":
- uuid_parameter = str(uuid.uuid4())
- try:
- logger.info("creating a new parameter")
- client.put_parameter(
- Name=uuid_key,
- Description="This is a unique id for each aws-instance-scheduler solution stack, for reporting metrics.",
- Value=uuid_parameter,
- Type="String",
- )
- except Exception as ex:
- logger.info("Failed to create a new parameter")
- logger.info(ex)
- else:
- logger.warning("Error creating UUID parameter.")
-
- logger.info("uuid_parameter {} ".format(uuid_parameter))
- data_dict = {
- "TimeStamp": str(datetime.utcnow().isoformat()),
- "UUID": uuid_parameter,
- "Data": metrics,
- "Solution": solution_id,
- "Version": VERSION,
- }
-
- data_json = safe_json(data_dict, indent=3)
- logger.info(INF_METRICS_DATA, data_json)
-
- headers = {
- "content-type": "application/json",
- "content-length": str(len(data_json)),
- }
-
- response = requests.post(url, data=data_json, headers=headers, timeout=300)
- response.raise_for_status()
- logger.debug(INF_METRICS_DATA_SENT, response.status_code, response.text)
- except Exception as exc:
- logger.warning((WARN_SENDING_METRICS_FAILED.format(str(exc))))
diff --git a/source/app/instance_scheduler/util/named_tuple_builder.py b/source/app/instance_scheduler/util/named_tuple_builder.py
deleted file mode 100644
index cf8a0043..00000000
--- a/source/app/instance_scheduler/util/named_tuple_builder.py
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-
-import collections
-
-
-# check for dictionaries
-def is_dict(o):
- return isinstance(o, type({}))
-
-
-def is_array(o):
- return isinstance(o, type([]))
-
-
-def tuple_name_func(name):
- result = "".join([c if c.isalnum() or c == "_" else "" for c in name.strip()])
- while result.startswith("_") or result[0].isdigit():
- result = result[1:]
- return result
-
-
-# converts a dictionary in a named tuple
-def as_namedtuple(name, d, deep=True, namefunc=None, excludes=None):
- name_func = namefunc if namefunc is not None else tuple_name_func
-
- if getattr(d, "keys") is None:
- return d
-
- if excludes is None:
- excludes = []
-
- dest = {}
-
- if deep:
- # deep copy to avoid modifications on input dictionaries
- for key in list(d):
- key_name = name_func(key)
- if is_dict(d[key]) and key not in excludes:
- dest[key_name] = as_namedtuple(
- key, d[key], namefunc=name_func, excludes=excludes, deep=True
- )
- elif is_array(d[key]) and key not in excludes:
- dest[key_name] = [
- as_namedtuple(
- key, i, namefunc=name_func, excludes=excludes, deep=True
- )
- for i in d[key]
- ]
- else:
- dest[key_name] = d[key]
- else:
- dest = {name_func(key): d[key] for key in list(d)}
-
- return collections.namedtuple(name_func(name), list(dest))(*dest.values())
diff --git a/source/app/instance_scheduler/util/scheduler_metrics.py b/source/app/instance_scheduler/util/scheduler_metrics.py
index e9e13695..0177bbfb 100644
--- a/source/app/instance_scheduler/util/scheduler_metrics.py
+++ b/source/app/instance_scheduler/util/scheduler_metrics.py
@@ -1,11 +1,21 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
+from datetime import datetime
+from typing import TYPE_CHECKING, Any, Optional
-
-import os
-
-from instance_scheduler import configuration
from instance_scheduler.boto_retry import get_client_with_standard_retry
+from instance_scheduler.configuration.instance_schedule import (
+ Instance,
+ InstanceSchedule,
+)
+from instance_scheduler.util.app_env import get_app_env
+
+if TYPE_CHECKING:
+ from mypy_boto3_cloudwatch.client import CloudWatchClient
+ from mypy_boto3_cloudwatch.type_defs import MetricDatumTypeDef
+else:
+ CloudWatchClient = object
+ MetricDatumTypeDef = object
class SchedulerMetrics:
@@ -21,27 +31,28 @@ class SchedulerMetrics:
ERRORS = "Errors"
WARNINGS = "Warnings"
- def __init__(self, dt, context=None):
+ def __init__(self, dt: datetime) -> None:
"""
Initializes instance of metrics wrapper
:param dt: date and time of the metrics data (typically the scheduling moment)
"""
self._dt = dt
- self._metrics_managed = {}
- self._metrics_running = {}
- self._context = context
- self._stack = os.getenv(configuration.ENV_STACK)
+ self._metrics_managed: dict[str, dict[str, int]] = {}
+ self._metrics_running: dict[str, dict[str, int]] = {}
+ self._stack = get_app_env().stack_name
self._namespace = "{}:{}".format(self._stack, SchedulerMetrics.NAMESPACE)
- self._metrics_client = None
+ self._metrics_client: Optional[CloudWatchClient] = None
@property
- def metrics_client(self):
+ def metrics_client(self) -> CloudWatchClient:
if self._metrics_client is None:
self._metrics_client = get_client_with_standard_retry("cloudwatch")
return self._metrics_client
- def add_schedule_metrics(self, service, schedule, instance):
+ def add_schedule_metrics(
+ self, service: str, schedule: InstanceSchedule, instance: Instance
+ ) -> None:
"""
Adds metrics data
:param service: name of the service
@@ -58,17 +69,22 @@ def add_schedule_metrics(self, service, schedule, instance):
)
self._metrics_running[service][schedule.name] = (
self._metrics_running[service].get(schedule.name, 0) + 1
- if instance.is_running
+ if instance["is_running"]
else 0
)
- def put_schedule_metrics(self):
+ def put_schedule_metrics(self) -> None:
"""
Writes the stores metrics data to cloudwatch metrics
:return:
"""
- def build_metric(service_name, schedule_name, metric_name, data):
+ def build_metric(
+ service_name: str,
+ schedule_name: str,
+ metric_name: str,
+ data: dict[str, Any],
+ ) -> MetricDatumTypeDef:
return {
"MetricName": metric_name,
"Dimensions": [
diff --git a/source/app/instance_scheduler/util/time.py b/source/app/instance_scheduler/util/time.py
new file mode 100644
index 00000000..1e0e886b
--- /dev/null
+++ b/source/app/instance_scheduler/util/time.py
@@ -0,0 +1,12 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from datetime import datetime
+
+
+def is_aware(dt: datetime) -> bool:
+ """
+ Returns `True` if the `datetime` is timezone-aware.
+
+ [[Documentation] Determining if an Object is Aware or Naive](https://docs.python.org/3/library/datetime.html#determining-if-an-object-is-aware-or-naive)
+ """
+ return dt.tzinfo is not None and dt.tzinfo.utcoffset(dt) is not None
diff --git a/source/app/mypy.ini b/source/app/mypy.ini
new file mode 100644
index 00000000..29943387
--- /dev/null
+++ b/source/app/mypy.ini
@@ -0,0 +1,47 @@
+[mypy]
+strict = True
+
+
+[mypy-instance_scheduler.configuration]
+disallow_untyped_calls = False
+
+[mypy-instance_scheduler.configuration.config_admin]
+disallow_untyped_calls = False
+
+[mypy-instance_scheduler.configuration.config_dynamodb_adapter]
+disallow_untyped_calls = False
+disallow_untyped_defs = False
+
+
+[mypy-instance_scheduler.configuration.scheduler_config_builder]
+disallow_untyped_calls = False
+disallow_untyped_defs = False
+
+
+[mypy-instance_scheduler.schedulers.instance_states]
+disallow_untyped_calls = False
+disallow_untyped_defs = False
+
+[mypy-instance_scheduler.schedulers.instance_scheduler]
+disallow_untyped_calls = False
+disallow_untyped_defs = False
+
+
+[mypy-instance_scheduler.util.dynamodb_utils]
+disallow_untyped_defs = False
+
+
+[mypy-instance_scheduler.handler.spoke_registration]
+disallow_untyped_calls = False
+
+
+[mypy-tests.handler.test_eventbus_request_handler]
+disallow_untyped_calls = False
+
+
+[mypy-tests.integration.conftest]
+disallow_untyped_calls = False
+
+
+[mypy-moto]
+ignore_missing_imports = True
diff --git a/source/app/poetry.lock b/source/app/poetry.lock
index ab3f2c53..6e7eb269 100644
--- a/source/app/poetry.lock
+++ b/source/app/poetry.lock
@@ -1,38 +1,57 @@
# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand.
+[[package]]
+name = "aws-lambda-powertools"
+version = "2.19.0"
+description = "Powertools for AWS Lambda (Python) is a developer toolkit to implement Serverless best practices and increase developer velocity."
+category = "dev"
+optional = false
+python-versions = ">=3.7.4,<4.0.0"
+files = [
+ {file = "aws_lambda_powertools-2.19.0-py3-none-any.whl", hash = "sha256:078aeb302857a8f69dfac470a8c7e957a2501fea638d547497aac18e94d824fd"},
+ {file = "aws_lambda_powertools-2.19.0.tar.gz", hash = "sha256:ed9a57a4748d5cda552056496264216ff0d7ea9908dc38fccc24818c7e556701"},
+]
+
+[package.dependencies]
+typing-extensions = ">=4.6.2,<5.0.0"
+
+[package.extras]
+all = ["aws-xray-sdk (>=2.8.0,<3.0.0)", "fastjsonschema (>=2.14.5,<3.0.0)", "pydantic (>=1.8.2,<2.0.0)"]
+aws-sdk = ["boto3 (>=1.20.32,<2.0.0)"]
+parser = ["pydantic (>=1.8.2,<2.0.0)"]
+tracer = ["aws-xray-sdk (>=2.8.0,<3.0.0)"]
+validation = ["fastjsonschema (>=2.14.5,<3.0.0)"]
+
[[package]]
name = "black"
-version = "23.3.0"
+version = "23.7.0"
description = "The uncompromising code formatter."
category = "dev"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "black-23.3.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915"},
- {file = "black-23.3.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9"},
- {file = "black-23.3.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2"},
- {file = "black-23.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c"},
- {file = "black-23.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c"},
- {file = "black-23.3.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6"},
- {file = "black-23.3.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b"},
- {file = "black-23.3.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d"},
- {file = "black-23.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70"},
- {file = "black-23.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326"},
- {file = "black-23.3.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b"},
- {file = "black-23.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2"},
- {file = "black-23.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925"},
- {file = "black-23.3.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27"},
- {file = "black-23.3.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331"},
- {file = "black-23.3.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5"},
- {file = "black-23.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961"},
- {file = "black-23.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8"},
- {file = "black-23.3.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30"},
- {file = "black-23.3.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3"},
- {file = "black-23.3.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266"},
- {file = "black-23.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab"},
- {file = "black-23.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb"},
- {file = "black-23.3.0-py3-none-any.whl", hash = "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4"},
- {file = "black-23.3.0.tar.gz", hash = "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940"},
+ {file = "black-23.7.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:5c4bc552ab52f6c1c506ccae05681fab58c3f72d59ae6e6639e8885e94fe2587"},
+ {file = "black-23.7.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:552513d5cd5694590d7ef6f46e1767a4df9af168d449ff767b13b084c020e63f"},
+ {file = "black-23.7.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:86cee259349b4448adb4ef9b204bb4467aae74a386bce85d56ba4f5dc0da27be"},
+ {file = "black-23.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:501387a9edcb75d7ae8a4412bb8749900386eaef258f1aefab18adddea1936bc"},
+ {file = "black-23.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995"},
+ {file = "black-23.7.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2"},
+ {file = "black-23.7.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:893695a76b140881531062d48476ebe4a48f5d1e9388177e175d76234ca247cd"},
+ {file = "black-23.7.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a"},
+ {file = "black-23.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831d8f54c3a8c8cf55f64d0422ee875eecac26f5f649fb6c1df65316b67c8926"},
+ {file = "black-23.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:7f3bf2dec7d541b4619b8ce526bda74a6b0bffc480a163fed32eb8b3c9aed8ad"},
+ {file = "black-23.7.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f"},
+ {file = "black-23.7.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:01ede61aac8c154b55f35301fac3e730baf0c9cf8120f65a9cd61a81cfb4a0c3"},
+ {file = "black-23.7.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:327a8c2550ddc573b51e2c352adb88143464bb9d92c10416feb86b0f5aee5ff6"},
+ {file = "black-23.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1c6022b86f83b632d06f2b02774134def5d4d4f1dac8bef16d90cda18ba28a"},
+ {file = "black-23.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:27eb7a0c71604d5de083757fbdb245b1a4fae60e9596514c6ec497eb63f95320"},
+ {file = "black-23.7.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:8417dbd2f57b5701492cd46edcecc4f9208dc75529bcf76c514864e48da867d9"},
+ {file = "black-23.7.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:47e56d83aad53ca140da0af87678fb38e44fd6bc0af71eebab2d1f59b1acf1d3"},
+ {file = "black-23.7.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:25cc308838fe71f7065df53aedd20327969d05671bac95b38fdf37ebe70ac087"},
+ {file = "black-23.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:642496b675095d423f9b8448243336f8ec71c9d4d57ec17bf795b67f08132a91"},
+ {file = "black-23.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:ad0014efc7acf0bd745792bd0d8857413652979200ab924fbf239062adc12491"},
+ {file = "black-23.7.0-py3-none-any.whl", hash = "sha256:9fd59d418c60c0348505f2ddf9609c1e1de8e7493eab96198fc89d9f865e7a96"},
+ {file = "black-23.7.0.tar.gz", hash = "sha256:022a582720b0d9480ed82576c920a8c1dde97cc38ff11d8d8859b3bd6ca9eedb"},
]
[package.dependencies]
@@ -42,7 +61,6 @@ packaging = ">=22.0"
pathspec = ">=0.9.0"
platformdirs = ">=2"
tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
-typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}
[package.extras]
colorama = ["colorama (>=0.4.3)"]
@@ -52,34 +70,407 @@ uvloop = ["uvloop (>=0.15.2)"]
[[package]]
name = "boto3"
-version = "1.26.112"
+version = "1.26.90"
description = "The AWS SDK for Python"
category = "dev"
optional = false
python-versions = ">= 3.7"
files = [
- {file = "boto3-1.26.112-py3-none-any.whl", hash = "sha256:03c2e1ddd29d993a6ab9b8a8fe184027957fc32bd405c496ad0c30311445925f"},
- {file = "boto3-1.26.112.tar.gz", hash = "sha256:4ea3319bba2e8ff7cd9560259ae64f073c7fb6312158aa375777687231cabe69"},
+ {file = "boto3-1.26.90-py3-none-any.whl", hash = "sha256:f1123076445f93fa85bf7ee956ae33041f2e077a6824e31929cc56ad31aeffc1"},
+ {file = "boto3-1.26.90.tar.gz", hash = "sha256:1d33abca60643d14f90a9e77d94085ebfd8f8bf8f157f582466f6b3a141bab8c"},
]
[package.dependencies]
-botocore = ">=1.29.112,<1.30.0"
+botocore = ">=1.29.90,<1.30.0"
jmespath = ">=0.7.1,<2.0.0"
s3transfer = ">=0.6.0,<0.7.0"
[package.extras]
crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
+[[package]]
+name = "boto3-stubs-lite"
+version = "1.26.90"
+description = "Type annotations for boto3 1.26.90 generated with mypy-boto3-builder 7.13.0"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "boto3-stubs-lite-1.26.90.tar.gz", hash = "sha256:ab0ca41fdd608661a612eff06461c5e722410bbd578ef181c53d31d459850668"},
+ {file = "boto3_stubs_lite-1.26.90-py3-none-any.whl", hash = "sha256:5d8ad25ff1e383d00a300b58f1a2368bfd9f23d195b1ccfef94f67f3a13e5436"},
+]
+
+[package.dependencies]
+botocore-stubs = "*"
+mypy-boto3-cloudwatch = {version = ">=1.26.0,<1.27.0", optional = true, markers = "extra == \"cloudwatch\""}
+mypy-boto3-dynamodb = {version = ">=1.26.0,<1.27.0", optional = true, markers = "extra == \"dynamodb\""}
+mypy-boto3-ec2 = {version = ">=1.26.0,<1.27.0", optional = true, markers = "extra == \"ec2\""}
+mypy-boto3-lambda = {version = ">=1.26.0,<1.27.0", optional = true, markers = "extra == \"lambda\""}
+mypy-boto3-logs = {version = ">=1.26.0,<1.27.0", optional = true, markers = "extra == \"logs\""}
+mypy-boto3-rds = {version = ">=1.26.0,<1.27.0", optional = true, markers = "extra == \"rds\""}
+mypy-boto3-resourcegroupstaggingapi = {version = ">=1.26.0,<1.27.0", optional = true, markers = "extra == \"resourcegroupstaggingapi\""}
+mypy-boto3-sns = {version = ">=1.26.0,<1.27.0", optional = true, markers = "extra == \"sns\""}
+mypy-boto3-ssm = {version = ">=1.26.0,<1.27.0", optional = true, markers = "extra == \"ssm\""}
+mypy-boto3-sts = {version = ">=1.26.0,<1.27.0", optional = true, markers = "extra == \"sts\""}
+types-s3transfer = "*"
+typing-extensions = ">=4.1.0"
+
+[package.extras]
+accessanalyzer = ["mypy-boto3-accessanalyzer (>=1.26.0,<1.27.0)"]
+account = ["mypy-boto3-account (>=1.26.0,<1.27.0)"]
+acm = ["mypy-boto3-acm (>=1.26.0,<1.27.0)"]
+acm-pca = ["mypy-boto3-acm-pca (>=1.26.0,<1.27.0)"]
+alexaforbusiness = ["mypy-boto3-alexaforbusiness (>=1.26.0,<1.27.0)"]
+all = ["mypy-boto3-accessanalyzer (>=1.26.0,<1.27.0)", "mypy-boto3-account (>=1.26.0,<1.27.0)", "mypy-boto3-acm (>=1.26.0,<1.27.0)", "mypy-boto3-acm-pca (>=1.26.0,<1.27.0)", "mypy-boto3-alexaforbusiness (>=1.26.0,<1.27.0)", "mypy-boto3-amp (>=1.26.0,<1.27.0)", "mypy-boto3-amplify (>=1.26.0,<1.27.0)", "mypy-boto3-amplifybackend (>=1.26.0,<1.27.0)", "mypy-boto3-amplifyuibuilder (>=1.26.0,<1.27.0)", "mypy-boto3-apigateway (>=1.26.0,<1.27.0)", "mypy-boto3-apigatewaymanagementapi (>=1.26.0,<1.27.0)", "mypy-boto3-apigatewayv2 (>=1.26.0,<1.27.0)", "mypy-boto3-appconfig (>=1.26.0,<1.27.0)", "mypy-boto3-appconfigdata (>=1.26.0,<1.27.0)", "mypy-boto3-appflow (>=1.26.0,<1.27.0)", "mypy-boto3-appintegrations (>=1.26.0,<1.27.0)", "mypy-boto3-application-autoscaling (>=1.26.0,<1.27.0)", "mypy-boto3-application-insights (>=1.26.0,<1.27.0)", "mypy-boto3-applicationcostprofiler (>=1.26.0,<1.27.0)", "mypy-boto3-appmesh (>=1.26.0,<1.27.0)", "mypy-boto3-apprunner (>=1.26.0,<1.27.0)", "mypy-boto3-appstream (>=1.26.0,<1.27.0)", "mypy-boto3-appsync (>=1.26.0,<1.27.0)", "mypy-boto3-arc-zonal-shift (>=1.26.0,<1.27.0)", "mypy-boto3-athena (>=1.26.0,<1.27.0)", "mypy-boto3-auditmanager (>=1.26.0,<1.27.0)", "mypy-boto3-autoscaling (>=1.26.0,<1.27.0)", "mypy-boto3-autoscaling-plans (>=1.26.0,<1.27.0)", "mypy-boto3-backup (>=1.26.0,<1.27.0)", "mypy-boto3-backup-gateway (>=1.26.0,<1.27.0)", "mypy-boto3-backupstorage (>=1.26.0,<1.27.0)", "mypy-boto3-batch (>=1.26.0,<1.27.0)", "mypy-boto3-billingconductor (>=1.26.0,<1.27.0)", "mypy-boto3-braket (>=1.26.0,<1.27.0)", "mypy-boto3-budgets (>=1.26.0,<1.27.0)", "mypy-boto3-ce (>=1.26.0,<1.27.0)", "mypy-boto3-chime (>=1.26.0,<1.27.0)", "mypy-boto3-chime-sdk-identity (>=1.26.0,<1.27.0)", "mypy-boto3-chime-sdk-media-pipelines (>=1.26.0,<1.27.0)", "mypy-boto3-chime-sdk-meetings (>=1.26.0,<1.27.0)", "mypy-boto3-chime-sdk-messaging (>=1.26.0,<1.27.0)", "mypy-boto3-chime-sdk-voice (>=1.26.0,<1.27.0)", "mypy-boto3-cleanrooms (>=1.26.0,<1.27.0)", "mypy-boto3-cloud9 (>=1.26.0,<1.27.0)", "mypy-boto3-cloudcontrol (>=1.26.0,<1.27.0)", "mypy-boto3-clouddirectory (>=1.26.0,<1.27.0)", "mypy-boto3-cloudformation (>=1.26.0,<1.27.0)", "mypy-boto3-cloudfront (>=1.26.0,<1.27.0)", "mypy-boto3-cloudhsm (>=1.26.0,<1.27.0)", "mypy-boto3-cloudhsmv2 (>=1.26.0,<1.27.0)", "mypy-boto3-cloudsearch (>=1.26.0,<1.27.0)", "mypy-boto3-cloudsearchdomain (>=1.26.0,<1.27.0)", "mypy-boto3-cloudtrail (>=1.26.0,<1.27.0)", "mypy-boto3-cloudtrail-data (>=1.26.0,<1.27.0)", "mypy-boto3-cloudwatch (>=1.26.0,<1.27.0)", "mypy-boto3-codeartifact (>=1.26.0,<1.27.0)", "mypy-boto3-codebuild (>=1.26.0,<1.27.0)", "mypy-boto3-codecatalyst (>=1.26.0,<1.27.0)", "mypy-boto3-codecommit (>=1.26.0,<1.27.0)", "mypy-boto3-codedeploy (>=1.26.0,<1.27.0)", "mypy-boto3-codeguru-reviewer (>=1.26.0,<1.27.0)", "mypy-boto3-codeguruprofiler (>=1.26.0,<1.27.0)", "mypy-boto3-codepipeline (>=1.26.0,<1.27.0)", "mypy-boto3-codestar (>=1.26.0,<1.27.0)", "mypy-boto3-codestar-connections (>=1.26.0,<1.27.0)", "mypy-boto3-codestar-notifications (>=1.26.0,<1.27.0)", "mypy-boto3-cognito-identity (>=1.26.0,<1.27.0)", "mypy-boto3-cognito-idp (>=1.26.0,<1.27.0)", "mypy-boto3-cognito-sync (>=1.26.0,<1.27.0)", "mypy-boto3-comprehend (>=1.26.0,<1.27.0)", "mypy-boto3-comprehendmedical (>=1.26.0,<1.27.0)", "mypy-boto3-compute-optimizer (>=1.26.0,<1.27.0)", "mypy-boto3-config (>=1.26.0,<1.27.0)", "mypy-boto3-connect (>=1.26.0,<1.27.0)", "mypy-boto3-connect-contact-lens (>=1.26.0,<1.27.0)", "mypy-boto3-connectcampaigns (>=1.26.0,<1.27.0)", "mypy-boto3-connectcases (>=1.26.0,<1.27.0)", "mypy-boto3-connectparticipant (>=1.26.0,<1.27.0)", "mypy-boto3-controltower (>=1.26.0,<1.27.0)", "mypy-boto3-cur (>=1.26.0,<1.27.0)", "mypy-boto3-customer-profiles (>=1.26.0,<1.27.0)", "mypy-boto3-databrew (>=1.26.0,<1.27.0)", "mypy-boto3-dataexchange (>=1.26.0,<1.27.0)", "mypy-boto3-datapipeline (>=1.26.0,<1.27.0)", "mypy-boto3-datasync (>=1.26.0,<1.27.0)", "mypy-boto3-dax (>=1.26.0,<1.27.0)", "mypy-boto3-detective (>=1.26.0,<1.27.0)", "mypy-boto3-devicefarm (>=1.26.0,<1.27.0)", "mypy-boto3-devops-guru (>=1.26.0,<1.27.0)", "mypy-boto3-directconnect (>=1.26.0,<1.27.0)", "mypy-boto3-discovery (>=1.26.0,<1.27.0)", "mypy-boto3-dlm (>=1.26.0,<1.27.0)", "mypy-boto3-dms (>=1.26.0,<1.27.0)", "mypy-boto3-docdb (>=1.26.0,<1.27.0)", "mypy-boto3-docdb-elastic (>=1.26.0,<1.27.0)", "mypy-boto3-drs (>=1.26.0,<1.27.0)", "mypy-boto3-ds (>=1.26.0,<1.27.0)", "mypy-boto3-dynamodb (>=1.26.0,<1.27.0)", "mypy-boto3-dynamodbstreams (>=1.26.0,<1.27.0)", "mypy-boto3-ebs (>=1.26.0,<1.27.0)", "mypy-boto3-ec2 (>=1.26.0,<1.27.0)", "mypy-boto3-ec2-instance-connect (>=1.26.0,<1.27.0)", "mypy-boto3-ecr (>=1.26.0,<1.27.0)", "mypy-boto3-ecr-public (>=1.26.0,<1.27.0)", "mypy-boto3-ecs (>=1.26.0,<1.27.0)", "mypy-boto3-efs (>=1.26.0,<1.27.0)", "mypy-boto3-eks (>=1.26.0,<1.27.0)", "mypy-boto3-elastic-inference (>=1.26.0,<1.27.0)", "mypy-boto3-elasticache (>=1.26.0,<1.27.0)", "mypy-boto3-elasticbeanstalk (>=1.26.0,<1.27.0)", "mypy-boto3-elastictranscoder (>=1.26.0,<1.27.0)", "mypy-boto3-elb (>=1.26.0,<1.27.0)", "mypy-boto3-elbv2 (>=1.26.0,<1.27.0)", "mypy-boto3-emr (>=1.26.0,<1.27.0)", "mypy-boto3-emr-containers (>=1.26.0,<1.27.0)", "mypy-boto3-emr-serverless (>=1.26.0,<1.27.0)", "mypy-boto3-es (>=1.26.0,<1.27.0)", "mypy-boto3-events (>=1.26.0,<1.27.0)", "mypy-boto3-evidently (>=1.26.0,<1.27.0)", "mypy-boto3-finspace (>=1.26.0,<1.27.0)", "mypy-boto3-finspace-data (>=1.26.0,<1.27.0)", "mypy-boto3-firehose (>=1.26.0,<1.27.0)", "mypy-boto3-fis (>=1.26.0,<1.27.0)", "mypy-boto3-fms (>=1.26.0,<1.27.0)", "mypy-boto3-forecast (>=1.26.0,<1.27.0)", "mypy-boto3-forecastquery (>=1.26.0,<1.27.0)", "mypy-boto3-frauddetector (>=1.26.0,<1.27.0)", "mypy-boto3-fsx (>=1.26.0,<1.27.0)", "mypy-boto3-gamelift (>=1.26.0,<1.27.0)", "mypy-boto3-gamesparks (>=1.26.0,<1.27.0)", "mypy-boto3-glacier (>=1.26.0,<1.27.0)", "mypy-boto3-globalaccelerator (>=1.26.0,<1.27.0)", "mypy-boto3-glue (>=1.26.0,<1.27.0)", "mypy-boto3-grafana (>=1.26.0,<1.27.0)", "mypy-boto3-greengrass (>=1.26.0,<1.27.0)", "mypy-boto3-greengrassv2 (>=1.26.0,<1.27.0)", "mypy-boto3-groundstation (>=1.26.0,<1.27.0)", "mypy-boto3-guardduty (>=1.26.0,<1.27.0)", "mypy-boto3-health (>=1.26.0,<1.27.0)", "mypy-boto3-healthlake (>=1.26.0,<1.27.0)", "mypy-boto3-honeycode (>=1.26.0,<1.27.0)", "mypy-boto3-iam (>=1.26.0,<1.27.0)", "mypy-boto3-identitystore (>=1.26.0,<1.27.0)", "mypy-boto3-imagebuilder (>=1.26.0,<1.27.0)", "mypy-boto3-importexport (>=1.26.0,<1.27.0)", "mypy-boto3-inspector (>=1.26.0,<1.27.0)", "mypy-boto3-inspector2 (>=1.26.0,<1.27.0)", "mypy-boto3-internetmonitor (>=1.26.0,<1.27.0)", "mypy-boto3-iot (>=1.26.0,<1.27.0)", "mypy-boto3-iot-data (>=1.26.0,<1.27.0)", "mypy-boto3-iot-jobs-data (>=1.26.0,<1.27.0)", "mypy-boto3-iot-roborunner (>=1.26.0,<1.27.0)", "mypy-boto3-iot1click-devices (>=1.26.0,<1.27.0)", "mypy-boto3-iot1click-projects (>=1.26.0,<1.27.0)", "mypy-boto3-iotanalytics (>=1.26.0,<1.27.0)", "mypy-boto3-iotdeviceadvisor (>=1.26.0,<1.27.0)", "mypy-boto3-iotevents (>=1.26.0,<1.27.0)", "mypy-boto3-iotevents-data (>=1.26.0,<1.27.0)", "mypy-boto3-iotfleethub (>=1.26.0,<1.27.0)", "mypy-boto3-iotfleetwise (>=1.26.0,<1.27.0)", "mypy-boto3-iotsecuretunneling (>=1.26.0,<1.27.0)", "mypy-boto3-iotsitewise (>=1.26.0,<1.27.0)", "mypy-boto3-iotthingsgraph (>=1.26.0,<1.27.0)", "mypy-boto3-iottwinmaker (>=1.26.0,<1.27.0)", "mypy-boto3-iotwireless (>=1.26.0,<1.27.0)", "mypy-boto3-ivs (>=1.26.0,<1.27.0)", "mypy-boto3-ivschat (>=1.26.0,<1.27.0)", "mypy-boto3-kafka (>=1.26.0,<1.27.0)", "mypy-boto3-kafkaconnect (>=1.26.0,<1.27.0)", "mypy-boto3-kendra (>=1.26.0,<1.27.0)", "mypy-boto3-kendra-ranking (>=1.26.0,<1.27.0)", "mypy-boto3-keyspaces (>=1.26.0,<1.27.0)", "mypy-boto3-kinesis (>=1.26.0,<1.27.0)", "mypy-boto3-kinesis-video-archived-media (>=1.26.0,<1.27.0)", "mypy-boto3-kinesis-video-media (>=1.26.0,<1.27.0)", "mypy-boto3-kinesis-video-signaling (>=1.26.0,<1.27.0)", "mypy-boto3-kinesis-video-webrtc-storage (>=1.26.0,<1.27.0)", "mypy-boto3-kinesisanalytics (>=1.26.0,<1.27.0)", "mypy-boto3-kinesisanalyticsv2 (>=1.26.0,<1.27.0)", "mypy-boto3-kinesisvideo (>=1.26.0,<1.27.0)", "mypy-boto3-kms (>=1.26.0,<1.27.0)", "mypy-boto3-lakeformation (>=1.26.0,<1.27.0)", "mypy-boto3-lambda (>=1.26.0,<1.27.0)", "mypy-boto3-lex-models (>=1.26.0,<1.27.0)", "mypy-boto3-lex-runtime (>=1.26.0,<1.27.0)", "mypy-boto3-lexv2-models (>=1.26.0,<1.27.0)", "mypy-boto3-lexv2-runtime (>=1.26.0,<1.27.0)", "mypy-boto3-license-manager (>=1.26.0,<1.27.0)", "mypy-boto3-license-manager-linux-subscriptions (>=1.26.0,<1.27.0)", "mypy-boto3-license-manager-user-subscriptions (>=1.26.0,<1.27.0)", "mypy-boto3-lightsail (>=1.26.0,<1.27.0)", "mypy-boto3-location (>=1.26.0,<1.27.0)", "mypy-boto3-logs (>=1.26.0,<1.27.0)", "mypy-boto3-lookoutequipment (>=1.26.0,<1.27.0)", "mypy-boto3-lookoutmetrics (>=1.26.0,<1.27.0)", "mypy-boto3-lookoutvision (>=1.26.0,<1.27.0)", "mypy-boto3-m2 (>=1.26.0,<1.27.0)", "mypy-boto3-machinelearning (>=1.26.0,<1.27.0)", "mypy-boto3-macie (>=1.26.0,<1.27.0)", "mypy-boto3-macie2 (>=1.26.0,<1.27.0)", "mypy-boto3-managedblockchain (>=1.26.0,<1.27.0)", "mypy-boto3-marketplace-catalog (>=1.26.0,<1.27.0)", "mypy-boto3-marketplace-entitlement (>=1.26.0,<1.27.0)", "mypy-boto3-marketplacecommerceanalytics (>=1.26.0,<1.27.0)", "mypy-boto3-mediaconnect (>=1.26.0,<1.27.0)", "mypy-boto3-mediaconvert (>=1.26.0,<1.27.0)", "mypy-boto3-medialive (>=1.26.0,<1.27.0)", "mypy-boto3-mediapackage (>=1.26.0,<1.27.0)", "mypy-boto3-mediapackage-vod (>=1.26.0,<1.27.0)", "mypy-boto3-mediastore (>=1.26.0,<1.27.0)", "mypy-boto3-mediastore-data (>=1.26.0,<1.27.0)", "mypy-boto3-mediatailor (>=1.26.0,<1.27.0)", "mypy-boto3-memorydb (>=1.26.0,<1.27.0)", "mypy-boto3-meteringmarketplace (>=1.26.0,<1.27.0)", "mypy-boto3-mgh (>=1.26.0,<1.27.0)", "mypy-boto3-mgn (>=1.26.0,<1.27.0)", "mypy-boto3-migration-hub-refactor-spaces (>=1.26.0,<1.27.0)", "mypy-boto3-migrationhub-config (>=1.26.0,<1.27.0)", "mypy-boto3-migrationhuborchestrator (>=1.26.0,<1.27.0)", "mypy-boto3-migrationhubstrategy (>=1.26.0,<1.27.0)", "mypy-boto3-mobile (>=1.26.0,<1.27.0)", "mypy-boto3-mq (>=1.26.0,<1.27.0)", "mypy-boto3-mturk (>=1.26.0,<1.27.0)", "mypy-boto3-mwaa (>=1.26.0,<1.27.0)", "mypy-boto3-neptune (>=1.26.0,<1.27.0)", "mypy-boto3-network-firewall (>=1.26.0,<1.27.0)", "mypy-boto3-networkmanager (>=1.26.0,<1.27.0)", "mypy-boto3-nimble (>=1.26.0,<1.27.0)", "mypy-boto3-oam (>=1.26.0,<1.27.0)", "mypy-boto3-omics (>=1.26.0,<1.27.0)", "mypy-boto3-opensearch (>=1.26.0,<1.27.0)", "mypy-boto3-opensearchserverless (>=1.26.0,<1.27.0)", "mypy-boto3-opsworks (>=1.26.0,<1.27.0)", "mypy-boto3-opsworkscm (>=1.26.0,<1.27.0)", "mypy-boto3-organizations (>=1.26.0,<1.27.0)", "mypy-boto3-outposts (>=1.26.0,<1.27.0)", "mypy-boto3-panorama (>=1.26.0,<1.27.0)", "mypy-boto3-personalize (>=1.26.0,<1.27.0)", "mypy-boto3-personalize-events (>=1.26.0,<1.27.0)", "mypy-boto3-personalize-runtime (>=1.26.0,<1.27.0)", "mypy-boto3-pi (>=1.26.0,<1.27.0)", "mypy-boto3-pinpoint (>=1.26.0,<1.27.0)", "mypy-boto3-pinpoint-email (>=1.26.0,<1.27.0)", "mypy-boto3-pinpoint-sms-voice (>=1.26.0,<1.27.0)", "mypy-boto3-pinpoint-sms-voice-v2 (>=1.26.0,<1.27.0)", "mypy-boto3-pipes (>=1.26.0,<1.27.0)", "mypy-boto3-polly (>=1.26.0,<1.27.0)", "mypy-boto3-pricing (>=1.26.0,<1.27.0)", "mypy-boto3-privatenetworks (>=1.26.0,<1.27.0)", "mypy-boto3-proton (>=1.26.0,<1.27.0)", "mypy-boto3-qldb (>=1.26.0,<1.27.0)", "mypy-boto3-qldb-session (>=1.26.0,<1.27.0)", "mypy-boto3-quicksight (>=1.26.0,<1.27.0)", "mypy-boto3-ram (>=1.26.0,<1.27.0)", "mypy-boto3-rbin (>=1.26.0,<1.27.0)", "mypy-boto3-rds (>=1.26.0,<1.27.0)", "mypy-boto3-rds-data (>=1.26.0,<1.27.0)", "mypy-boto3-redshift (>=1.26.0,<1.27.0)", "mypy-boto3-redshift-data (>=1.26.0,<1.27.0)", "mypy-boto3-redshift-serverless (>=1.26.0,<1.27.0)", "mypy-boto3-rekognition (>=1.26.0,<1.27.0)", "mypy-boto3-resiliencehub (>=1.26.0,<1.27.0)", "mypy-boto3-resource-explorer-2 (>=1.26.0,<1.27.0)", "mypy-boto3-resource-groups (>=1.26.0,<1.27.0)", "mypy-boto3-resourcegroupstaggingapi (>=1.26.0,<1.27.0)", "mypy-boto3-robomaker (>=1.26.0,<1.27.0)", "mypy-boto3-rolesanywhere (>=1.26.0,<1.27.0)", "mypy-boto3-route53 (>=1.26.0,<1.27.0)", "mypy-boto3-route53-recovery-cluster (>=1.26.0,<1.27.0)", "mypy-boto3-route53-recovery-control-config (>=1.26.0,<1.27.0)", "mypy-boto3-route53-recovery-readiness (>=1.26.0,<1.27.0)", "mypy-boto3-route53domains (>=1.26.0,<1.27.0)", "mypy-boto3-route53resolver (>=1.26.0,<1.27.0)", "mypy-boto3-rum (>=1.26.0,<1.27.0)", "mypy-boto3-s3 (>=1.26.0,<1.27.0)", "mypy-boto3-s3control (>=1.26.0,<1.27.0)", "mypy-boto3-s3outposts (>=1.26.0,<1.27.0)", "mypy-boto3-sagemaker (>=1.26.0,<1.27.0)", "mypy-boto3-sagemaker-a2i-runtime (>=1.26.0,<1.27.0)", "mypy-boto3-sagemaker-edge (>=1.26.0,<1.27.0)", "mypy-boto3-sagemaker-featurestore-runtime (>=1.26.0,<1.27.0)", "mypy-boto3-sagemaker-geospatial (>=1.26.0,<1.27.0)", "mypy-boto3-sagemaker-metrics (>=1.26.0,<1.27.0)", "mypy-boto3-sagemaker-runtime (>=1.26.0,<1.27.0)", "mypy-boto3-savingsplans (>=1.26.0,<1.27.0)", "mypy-boto3-scheduler (>=1.26.0,<1.27.0)", "mypy-boto3-schemas (>=1.26.0,<1.27.0)", "mypy-boto3-sdb (>=1.26.0,<1.27.0)", "mypy-boto3-secretsmanager (>=1.26.0,<1.27.0)", "mypy-boto3-securityhub (>=1.26.0,<1.27.0)", "mypy-boto3-securitylake (>=1.26.0,<1.27.0)", "mypy-boto3-serverlessrepo (>=1.26.0,<1.27.0)", "mypy-boto3-service-quotas (>=1.26.0,<1.27.0)", "mypy-boto3-servicecatalog (>=1.26.0,<1.27.0)", "mypy-boto3-servicecatalog-appregistry (>=1.26.0,<1.27.0)", "mypy-boto3-servicediscovery (>=1.26.0,<1.27.0)", "mypy-boto3-ses (>=1.26.0,<1.27.0)", "mypy-boto3-sesv2 (>=1.26.0,<1.27.0)", "mypy-boto3-shield (>=1.26.0,<1.27.0)", "mypy-boto3-signer (>=1.26.0,<1.27.0)", "mypy-boto3-simspaceweaver (>=1.26.0,<1.27.0)", "mypy-boto3-sms (>=1.26.0,<1.27.0)", "mypy-boto3-sms-voice (>=1.26.0,<1.27.0)", "mypy-boto3-snow-device-management (>=1.26.0,<1.27.0)", "mypy-boto3-snowball (>=1.26.0,<1.27.0)", "mypy-boto3-sns (>=1.26.0,<1.27.0)", "mypy-boto3-sqs (>=1.26.0,<1.27.0)", "mypy-boto3-ssm (>=1.26.0,<1.27.0)", "mypy-boto3-ssm-contacts (>=1.26.0,<1.27.0)", "mypy-boto3-ssm-incidents (>=1.26.0,<1.27.0)", "mypy-boto3-ssm-sap (>=1.26.0,<1.27.0)", "mypy-boto3-sso (>=1.26.0,<1.27.0)", "mypy-boto3-sso-admin (>=1.26.0,<1.27.0)", "mypy-boto3-sso-oidc (>=1.26.0,<1.27.0)", "mypy-boto3-stepfunctions (>=1.26.0,<1.27.0)", "mypy-boto3-storagegateway (>=1.26.0,<1.27.0)", "mypy-boto3-sts (>=1.26.0,<1.27.0)", "mypy-boto3-support (>=1.26.0,<1.27.0)", "mypy-boto3-support-app (>=1.26.0,<1.27.0)", "mypy-boto3-swf (>=1.26.0,<1.27.0)", "mypy-boto3-synthetics (>=1.26.0,<1.27.0)", "mypy-boto3-textract (>=1.26.0,<1.27.0)", "mypy-boto3-timestream-query (>=1.26.0,<1.27.0)", "mypy-boto3-timestream-write (>=1.26.0,<1.27.0)", "mypy-boto3-tnb (>=1.26.0,<1.27.0)", "mypy-boto3-transcribe (>=1.26.0,<1.27.0)", "mypy-boto3-transfer (>=1.26.0,<1.27.0)", "mypy-boto3-translate (>=1.26.0,<1.27.0)", "mypy-boto3-voice-id (>=1.26.0,<1.27.0)", "mypy-boto3-waf (>=1.26.0,<1.27.0)", "mypy-boto3-waf-regional (>=1.26.0,<1.27.0)", "mypy-boto3-wafv2 (>=1.26.0,<1.27.0)", "mypy-boto3-wellarchitected (>=1.26.0,<1.27.0)", "mypy-boto3-wisdom (>=1.26.0,<1.27.0)", "mypy-boto3-workdocs (>=1.26.0,<1.27.0)", "mypy-boto3-worklink (>=1.26.0,<1.27.0)", "mypy-boto3-workmail (>=1.26.0,<1.27.0)", "mypy-boto3-workmailmessageflow (>=1.26.0,<1.27.0)", "mypy-boto3-workspaces (>=1.26.0,<1.27.0)", "mypy-boto3-workspaces-web (>=1.26.0,<1.27.0)", "mypy-boto3-xray (>=1.26.0,<1.27.0)"]
+amp = ["mypy-boto3-amp (>=1.26.0,<1.27.0)"]
+amplify = ["mypy-boto3-amplify (>=1.26.0,<1.27.0)"]
+amplifybackend = ["mypy-boto3-amplifybackend (>=1.26.0,<1.27.0)"]
+amplifyuibuilder = ["mypy-boto3-amplifyuibuilder (>=1.26.0,<1.27.0)"]
+apigateway = ["mypy-boto3-apigateway (>=1.26.0,<1.27.0)"]
+apigatewaymanagementapi = ["mypy-boto3-apigatewaymanagementapi (>=1.26.0,<1.27.0)"]
+apigatewayv2 = ["mypy-boto3-apigatewayv2 (>=1.26.0,<1.27.0)"]
+appconfig = ["mypy-boto3-appconfig (>=1.26.0,<1.27.0)"]
+appconfigdata = ["mypy-boto3-appconfigdata (>=1.26.0,<1.27.0)"]
+appflow = ["mypy-boto3-appflow (>=1.26.0,<1.27.0)"]
+appintegrations = ["mypy-boto3-appintegrations (>=1.26.0,<1.27.0)"]
+application-autoscaling = ["mypy-boto3-application-autoscaling (>=1.26.0,<1.27.0)"]
+application-insights = ["mypy-boto3-application-insights (>=1.26.0,<1.27.0)"]
+applicationcostprofiler = ["mypy-boto3-applicationcostprofiler (>=1.26.0,<1.27.0)"]
+appmesh = ["mypy-boto3-appmesh (>=1.26.0,<1.27.0)"]
+apprunner = ["mypy-boto3-apprunner (>=1.26.0,<1.27.0)"]
+appstream = ["mypy-boto3-appstream (>=1.26.0,<1.27.0)"]
+appsync = ["mypy-boto3-appsync (>=1.26.0,<1.27.0)"]
+arc-zonal-shift = ["mypy-boto3-arc-zonal-shift (>=1.26.0,<1.27.0)"]
+athena = ["mypy-boto3-athena (>=1.26.0,<1.27.0)"]
+auditmanager = ["mypy-boto3-auditmanager (>=1.26.0,<1.27.0)"]
+autoscaling = ["mypy-boto3-autoscaling (>=1.26.0,<1.27.0)"]
+autoscaling-plans = ["mypy-boto3-autoscaling-plans (>=1.26.0,<1.27.0)"]
+backup = ["mypy-boto3-backup (>=1.26.0,<1.27.0)"]
+backup-gateway = ["mypy-boto3-backup-gateway (>=1.26.0,<1.27.0)"]
+backupstorage = ["mypy-boto3-backupstorage (>=1.26.0,<1.27.0)"]
+batch = ["mypy-boto3-batch (>=1.26.0,<1.27.0)"]
+billingconductor = ["mypy-boto3-billingconductor (>=1.26.0,<1.27.0)"]
+boto3 = ["boto3 (==1.26.90)", "botocore (==1.29.90)"]
+braket = ["mypy-boto3-braket (>=1.26.0,<1.27.0)"]
+budgets = ["mypy-boto3-budgets (>=1.26.0,<1.27.0)"]
+ce = ["mypy-boto3-ce (>=1.26.0,<1.27.0)"]
+chime = ["mypy-boto3-chime (>=1.26.0,<1.27.0)"]
+chime-sdk-identity = ["mypy-boto3-chime-sdk-identity (>=1.26.0,<1.27.0)"]
+chime-sdk-media-pipelines = ["mypy-boto3-chime-sdk-media-pipelines (>=1.26.0,<1.27.0)"]
+chime-sdk-meetings = ["mypy-boto3-chime-sdk-meetings (>=1.26.0,<1.27.0)"]
+chime-sdk-messaging = ["mypy-boto3-chime-sdk-messaging (>=1.26.0,<1.27.0)"]
+chime-sdk-voice = ["mypy-boto3-chime-sdk-voice (>=1.26.0,<1.27.0)"]
+cleanrooms = ["mypy-boto3-cleanrooms (>=1.26.0,<1.27.0)"]
+cloud9 = ["mypy-boto3-cloud9 (>=1.26.0,<1.27.0)"]
+cloudcontrol = ["mypy-boto3-cloudcontrol (>=1.26.0,<1.27.0)"]
+clouddirectory = ["mypy-boto3-clouddirectory (>=1.26.0,<1.27.0)"]
+cloudformation = ["mypy-boto3-cloudformation (>=1.26.0,<1.27.0)"]
+cloudfront = ["mypy-boto3-cloudfront (>=1.26.0,<1.27.0)"]
+cloudhsm = ["mypy-boto3-cloudhsm (>=1.26.0,<1.27.0)"]
+cloudhsmv2 = ["mypy-boto3-cloudhsmv2 (>=1.26.0,<1.27.0)"]
+cloudsearch = ["mypy-boto3-cloudsearch (>=1.26.0,<1.27.0)"]
+cloudsearchdomain = ["mypy-boto3-cloudsearchdomain (>=1.26.0,<1.27.0)"]
+cloudtrail = ["mypy-boto3-cloudtrail (>=1.26.0,<1.27.0)"]
+cloudtrail-data = ["mypy-boto3-cloudtrail-data (>=1.26.0,<1.27.0)"]
+cloudwatch = ["mypy-boto3-cloudwatch (>=1.26.0,<1.27.0)"]
+codeartifact = ["mypy-boto3-codeartifact (>=1.26.0,<1.27.0)"]
+codebuild = ["mypy-boto3-codebuild (>=1.26.0,<1.27.0)"]
+codecatalyst = ["mypy-boto3-codecatalyst (>=1.26.0,<1.27.0)"]
+codecommit = ["mypy-boto3-codecommit (>=1.26.0,<1.27.0)"]
+codedeploy = ["mypy-boto3-codedeploy (>=1.26.0,<1.27.0)"]
+codeguru-reviewer = ["mypy-boto3-codeguru-reviewer (>=1.26.0,<1.27.0)"]
+codeguruprofiler = ["mypy-boto3-codeguruprofiler (>=1.26.0,<1.27.0)"]
+codepipeline = ["mypy-boto3-codepipeline (>=1.26.0,<1.27.0)"]
+codestar = ["mypy-boto3-codestar (>=1.26.0,<1.27.0)"]
+codestar-connections = ["mypy-boto3-codestar-connections (>=1.26.0,<1.27.0)"]
+codestar-notifications = ["mypy-boto3-codestar-notifications (>=1.26.0,<1.27.0)"]
+cognito-identity = ["mypy-boto3-cognito-identity (>=1.26.0,<1.27.0)"]
+cognito-idp = ["mypy-boto3-cognito-idp (>=1.26.0,<1.27.0)"]
+cognito-sync = ["mypy-boto3-cognito-sync (>=1.26.0,<1.27.0)"]
+comprehend = ["mypy-boto3-comprehend (>=1.26.0,<1.27.0)"]
+comprehendmedical = ["mypy-boto3-comprehendmedical (>=1.26.0,<1.27.0)"]
+compute-optimizer = ["mypy-boto3-compute-optimizer (>=1.26.0,<1.27.0)"]
+config = ["mypy-boto3-config (>=1.26.0,<1.27.0)"]
+connect = ["mypy-boto3-connect (>=1.26.0,<1.27.0)"]
+connect-contact-lens = ["mypy-boto3-connect-contact-lens (>=1.26.0,<1.27.0)"]
+connectcampaigns = ["mypy-boto3-connectcampaigns (>=1.26.0,<1.27.0)"]
+connectcases = ["mypy-boto3-connectcases (>=1.26.0,<1.27.0)"]
+connectparticipant = ["mypy-boto3-connectparticipant (>=1.26.0,<1.27.0)"]
+controltower = ["mypy-boto3-controltower (>=1.26.0,<1.27.0)"]
+cur = ["mypy-boto3-cur (>=1.26.0,<1.27.0)"]
+customer-profiles = ["mypy-boto3-customer-profiles (>=1.26.0,<1.27.0)"]
+databrew = ["mypy-boto3-databrew (>=1.26.0,<1.27.0)"]
+dataexchange = ["mypy-boto3-dataexchange (>=1.26.0,<1.27.0)"]
+datapipeline = ["mypy-boto3-datapipeline (>=1.26.0,<1.27.0)"]
+datasync = ["mypy-boto3-datasync (>=1.26.0,<1.27.0)"]
+dax = ["mypy-boto3-dax (>=1.26.0,<1.27.0)"]
+detective = ["mypy-boto3-detective (>=1.26.0,<1.27.0)"]
+devicefarm = ["mypy-boto3-devicefarm (>=1.26.0,<1.27.0)"]
+devops-guru = ["mypy-boto3-devops-guru (>=1.26.0,<1.27.0)"]
+directconnect = ["mypy-boto3-directconnect (>=1.26.0,<1.27.0)"]
+discovery = ["mypy-boto3-discovery (>=1.26.0,<1.27.0)"]
+dlm = ["mypy-boto3-dlm (>=1.26.0,<1.27.0)"]
+dms = ["mypy-boto3-dms (>=1.26.0,<1.27.0)"]
+docdb = ["mypy-boto3-docdb (>=1.26.0,<1.27.0)"]
+docdb-elastic = ["mypy-boto3-docdb-elastic (>=1.26.0,<1.27.0)"]
+drs = ["mypy-boto3-drs (>=1.26.0,<1.27.0)"]
+ds = ["mypy-boto3-ds (>=1.26.0,<1.27.0)"]
+dynamodb = ["mypy-boto3-dynamodb (>=1.26.0,<1.27.0)"]
+dynamodbstreams = ["mypy-boto3-dynamodbstreams (>=1.26.0,<1.27.0)"]
+ebs = ["mypy-boto3-ebs (>=1.26.0,<1.27.0)"]
+ec2 = ["mypy-boto3-ec2 (>=1.26.0,<1.27.0)"]
+ec2-instance-connect = ["mypy-boto3-ec2-instance-connect (>=1.26.0,<1.27.0)"]
+ecr = ["mypy-boto3-ecr (>=1.26.0,<1.27.0)"]
+ecr-public = ["mypy-boto3-ecr-public (>=1.26.0,<1.27.0)"]
+ecs = ["mypy-boto3-ecs (>=1.26.0,<1.27.0)"]
+efs = ["mypy-boto3-efs (>=1.26.0,<1.27.0)"]
+eks = ["mypy-boto3-eks (>=1.26.0,<1.27.0)"]
+elastic-inference = ["mypy-boto3-elastic-inference (>=1.26.0,<1.27.0)"]
+elasticache = ["mypy-boto3-elasticache (>=1.26.0,<1.27.0)"]
+elasticbeanstalk = ["mypy-boto3-elasticbeanstalk (>=1.26.0,<1.27.0)"]
+elastictranscoder = ["mypy-boto3-elastictranscoder (>=1.26.0,<1.27.0)"]
+elb = ["mypy-boto3-elb (>=1.26.0,<1.27.0)"]
+elbv2 = ["mypy-boto3-elbv2 (>=1.26.0,<1.27.0)"]
+emr = ["mypy-boto3-emr (>=1.26.0,<1.27.0)"]
+emr-containers = ["mypy-boto3-emr-containers (>=1.26.0,<1.27.0)"]
+emr-serverless = ["mypy-boto3-emr-serverless (>=1.26.0,<1.27.0)"]
+es = ["mypy-boto3-es (>=1.26.0,<1.27.0)"]
+essential = ["mypy-boto3-cloudformation (>=1.26.0,<1.27.0)", "mypy-boto3-dynamodb (>=1.26.0,<1.27.0)", "mypy-boto3-ec2 (>=1.26.0,<1.27.0)", "mypy-boto3-lambda (>=1.26.0,<1.27.0)", "mypy-boto3-rds (>=1.26.0,<1.27.0)", "mypy-boto3-s3 (>=1.26.0,<1.27.0)", "mypy-boto3-sqs (>=1.26.0,<1.27.0)"]
+events = ["mypy-boto3-events (>=1.26.0,<1.27.0)"]
+evidently = ["mypy-boto3-evidently (>=1.26.0,<1.27.0)"]
+finspace = ["mypy-boto3-finspace (>=1.26.0,<1.27.0)"]
+finspace-data = ["mypy-boto3-finspace-data (>=1.26.0,<1.27.0)"]
+firehose = ["mypy-boto3-firehose (>=1.26.0,<1.27.0)"]
+fis = ["mypy-boto3-fis (>=1.26.0,<1.27.0)"]
+fms = ["mypy-boto3-fms (>=1.26.0,<1.27.0)"]
+forecast = ["mypy-boto3-forecast (>=1.26.0,<1.27.0)"]
+forecastquery = ["mypy-boto3-forecastquery (>=1.26.0,<1.27.0)"]
+frauddetector = ["mypy-boto3-frauddetector (>=1.26.0,<1.27.0)"]
+fsx = ["mypy-boto3-fsx (>=1.26.0,<1.27.0)"]
+gamelift = ["mypy-boto3-gamelift (>=1.26.0,<1.27.0)"]
+gamesparks = ["mypy-boto3-gamesparks (>=1.26.0,<1.27.0)"]
+glacier = ["mypy-boto3-glacier (>=1.26.0,<1.27.0)"]
+globalaccelerator = ["mypy-boto3-globalaccelerator (>=1.26.0,<1.27.0)"]
+glue = ["mypy-boto3-glue (>=1.26.0,<1.27.0)"]
+grafana = ["mypy-boto3-grafana (>=1.26.0,<1.27.0)"]
+greengrass = ["mypy-boto3-greengrass (>=1.26.0,<1.27.0)"]
+greengrassv2 = ["mypy-boto3-greengrassv2 (>=1.26.0,<1.27.0)"]
+groundstation = ["mypy-boto3-groundstation (>=1.26.0,<1.27.0)"]
+guardduty = ["mypy-boto3-guardduty (>=1.26.0,<1.27.0)"]
+health = ["mypy-boto3-health (>=1.26.0,<1.27.0)"]
+healthlake = ["mypy-boto3-healthlake (>=1.26.0,<1.27.0)"]
+honeycode = ["mypy-boto3-honeycode (>=1.26.0,<1.27.0)"]
+iam = ["mypy-boto3-iam (>=1.26.0,<1.27.0)"]
+identitystore = ["mypy-boto3-identitystore (>=1.26.0,<1.27.0)"]
+imagebuilder = ["mypy-boto3-imagebuilder (>=1.26.0,<1.27.0)"]
+importexport = ["mypy-boto3-importexport (>=1.26.0,<1.27.0)"]
+inspector = ["mypy-boto3-inspector (>=1.26.0,<1.27.0)"]
+inspector2 = ["mypy-boto3-inspector2 (>=1.26.0,<1.27.0)"]
+internetmonitor = ["mypy-boto3-internetmonitor (>=1.26.0,<1.27.0)"]
+iot = ["mypy-boto3-iot (>=1.26.0,<1.27.0)"]
+iot-data = ["mypy-boto3-iot-data (>=1.26.0,<1.27.0)"]
+iot-jobs-data = ["mypy-boto3-iot-jobs-data (>=1.26.0,<1.27.0)"]
+iot-roborunner = ["mypy-boto3-iot-roborunner (>=1.26.0,<1.27.0)"]
+iot1click-devices = ["mypy-boto3-iot1click-devices (>=1.26.0,<1.27.0)"]
+iot1click-projects = ["mypy-boto3-iot1click-projects (>=1.26.0,<1.27.0)"]
+iotanalytics = ["mypy-boto3-iotanalytics (>=1.26.0,<1.27.0)"]
+iotdeviceadvisor = ["mypy-boto3-iotdeviceadvisor (>=1.26.0,<1.27.0)"]
+iotevents = ["mypy-boto3-iotevents (>=1.26.0,<1.27.0)"]
+iotevents-data = ["mypy-boto3-iotevents-data (>=1.26.0,<1.27.0)"]
+iotfleethub = ["mypy-boto3-iotfleethub (>=1.26.0,<1.27.0)"]
+iotfleetwise = ["mypy-boto3-iotfleetwise (>=1.26.0,<1.27.0)"]
+iotsecuretunneling = ["mypy-boto3-iotsecuretunneling (>=1.26.0,<1.27.0)"]
+iotsitewise = ["mypy-boto3-iotsitewise (>=1.26.0,<1.27.0)"]
+iotthingsgraph = ["mypy-boto3-iotthingsgraph (>=1.26.0,<1.27.0)"]
+iottwinmaker = ["mypy-boto3-iottwinmaker (>=1.26.0,<1.27.0)"]
+iotwireless = ["mypy-boto3-iotwireless (>=1.26.0,<1.27.0)"]
+ivs = ["mypy-boto3-ivs (>=1.26.0,<1.27.0)"]
+ivschat = ["mypy-boto3-ivschat (>=1.26.0,<1.27.0)"]
+kafka = ["mypy-boto3-kafka (>=1.26.0,<1.27.0)"]
+kafkaconnect = ["mypy-boto3-kafkaconnect (>=1.26.0,<1.27.0)"]
+kendra = ["mypy-boto3-kendra (>=1.26.0,<1.27.0)"]
+kendra-ranking = ["mypy-boto3-kendra-ranking (>=1.26.0,<1.27.0)"]
+keyspaces = ["mypy-boto3-keyspaces (>=1.26.0,<1.27.0)"]
+kinesis = ["mypy-boto3-kinesis (>=1.26.0,<1.27.0)"]
+kinesis-video-archived-media = ["mypy-boto3-kinesis-video-archived-media (>=1.26.0,<1.27.0)"]
+kinesis-video-media = ["mypy-boto3-kinesis-video-media (>=1.26.0,<1.27.0)"]
+kinesis-video-signaling = ["mypy-boto3-kinesis-video-signaling (>=1.26.0,<1.27.0)"]
+kinesis-video-webrtc-storage = ["mypy-boto3-kinesis-video-webrtc-storage (>=1.26.0,<1.27.0)"]
+kinesisanalytics = ["mypy-boto3-kinesisanalytics (>=1.26.0,<1.27.0)"]
+kinesisanalyticsv2 = ["mypy-boto3-kinesisanalyticsv2 (>=1.26.0,<1.27.0)"]
+kinesisvideo = ["mypy-boto3-kinesisvideo (>=1.26.0,<1.27.0)"]
+kms = ["mypy-boto3-kms (>=1.26.0,<1.27.0)"]
+lakeformation = ["mypy-boto3-lakeformation (>=1.26.0,<1.27.0)"]
+lambda = ["mypy-boto3-lambda (>=1.26.0,<1.27.0)"]
+lex-models = ["mypy-boto3-lex-models (>=1.26.0,<1.27.0)"]
+lex-runtime = ["mypy-boto3-lex-runtime (>=1.26.0,<1.27.0)"]
+lexv2-models = ["mypy-boto3-lexv2-models (>=1.26.0,<1.27.0)"]
+lexv2-runtime = ["mypy-boto3-lexv2-runtime (>=1.26.0,<1.27.0)"]
+license-manager = ["mypy-boto3-license-manager (>=1.26.0,<1.27.0)"]
+license-manager-linux-subscriptions = ["mypy-boto3-license-manager-linux-subscriptions (>=1.26.0,<1.27.0)"]
+license-manager-user-subscriptions = ["mypy-boto3-license-manager-user-subscriptions (>=1.26.0,<1.27.0)"]
+lightsail = ["mypy-boto3-lightsail (>=1.26.0,<1.27.0)"]
+location = ["mypy-boto3-location (>=1.26.0,<1.27.0)"]
+logs = ["mypy-boto3-logs (>=1.26.0,<1.27.0)"]
+lookoutequipment = ["mypy-boto3-lookoutequipment (>=1.26.0,<1.27.0)"]
+lookoutmetrics = ["mypy-boto3-lookoutmetrics (>=1.26.0,<1.27.0)"]
+lookoutvision = ["mypy-boto3-lookoutvision (>=1.26.0,<1.27.0)"]
+m2 = ["mypy-boto3-m2 (>=1.26.0,<1.27.0)"]
+machinelearning = ["mypy-boto3-machinelearning (>=1.26.0,<1.27.0)"]
+macie = ["mypy-boto3-macie (>=1.26.0,<1.27.0)"]
+macie2 = ["mypy-boto3-macie2 (>=1.26.0,<1.27.0)"]
+managedblockchain = ["mypy-boto3-managedblockchain (>=1.26.0,<1.27.0)"]
+marketplace-catalog = ["mypy-boto3-marketplace-catalog (>=1.26.0,<1.27.0)"]
+marketplace-entitlement = ["mypy-boto3-marketplace-entitlement (>=1.26.0,<1.27.0)"]
+marketplacecommerceanalytics = ["mypy-boto3-marketplacecommerceanalytics (>=1.26.0,<1.27.0)"]
+mediaconnect = ["mypy-boto3-mediaconnect (>=1.26.0,<1.27.0)"]
+mediaconvert = ["mypy-boto3-mediaconvert (>=1.26.0,<1.27.0)"]
+medialive = ["mypy-boto3-medialive (>=1.26.0,<1.27.0)"]
+mediapackage = ["mypy-boto3-mediapackage (>=1.26.0,<1.27.0)"]
+mediapackage-vod = ["mypy-boto3-mediapackage-vod (>=1.26.0,<1.27.0)"]
+mediastore = ["mypy-boto3-mediastore (>=1.26.0,<1.27.0)"]
+mediastore-data = ["mypy-boto3-mediastore-data (>=1.26.0,<1.27.0)"]
+mediatailor = ["mypy-boto3-mediatailor (>=1.26.0,<1.27.0)"]
+memorydb = ["mypy-boto3-memorydb (>=1.26.0,<1.27.0)"]
+meteringmarketplace = ["mypy-boto3-meteringmarketplace (>=1.26.0,<1.27.0)"]
+mgh = ["mypy-boto3-mgh (>=1.26.0,<1.27.0)"]
+mgn = ["mypy-boto3-mgn (>=1.26.0,<1.27.0)"]
+migration-hub-refactor-spaces = ["mypy-boto3-migration-hub-refactor-spaces (>=1.26.0,<1.27.0)"]
+migrationhub-config = ["mypy-boto3-migrationhub-config (>=1.26.0,<1.27.0)"]
+migrationhuborchestrator = ["mypy-boto3-migrationhuborchestrator (>=1.26.0,<1.27.0)"]
+migrationhubstrategy = ["mypy-boto3-migrationhubstrategy (>=1.26.0,<1.27.0)"]
+mobile = ["mypy-boto3-mobile (>=1.26.0,<1.27.0)"]
+mq = ["mypy-boto3-mq (>=1.26.0,<1.27.0)"]
+mturk = ["mypy-boto3-mturk (>=1.26.0,<1.27.0)"]
+mwaa = ["mypy-boto3-mwaa (>=1.26.0,<1.27.0)"]
+neptune = ["mypy-boto3-neptune (>=1.26.0,<1.27.0)"]
+network-firewall = ["mypy-boto3-network-firewall (>=1.26.0,<1.27.0)"]
+networkmanager = ["mypy-boto3-networkmanager (>=1.26.0,<1.27.0)"]
+nimble = ["mypy-boto3-nimble (>=1.26.0,<1.27.0)"]
+oam = ["mypy-boto3-oam (>=1.26.0,<1.27.0)"]
+omics = ["mypy-boto3-omics (>=1.26.0,<1.27.0)"]
+opensearch = ["mypy-boto3-opensearch (>=1.26.0,<1.27.0)"]
+opensearchserverless = ["mypy-boto3-opensearchserverless (>=1.26.0,<1.27.0)"]
+opsworks = ["mypy-boto3-opsworks (>=1.26.0,<1.27.0)"]
+opsworkscm = ["mypy-boto3-opsworkscm (>=1.26.0,<1.27.0)"]
+organizations = ["mypy-boto3-organizations (>=1.26.0,<1.27.0)"]
+outposts = ["mypy-boto3-outposts (>=1.26.0,<1.27.0)"]
+panorama = ["mypy-boto3-panorama (>=1.26.0,<1.27.0)"]
+personalize = ["mypy-boto3-personalize (>=1.26.0,<1.27.0)"]
+personalize-events = ["mypy-boto3-personalize-events (>=1.26.0,<1.27.0)"]
+personalize-runtime = ["mypy-boto3-personalize-runtime (>=1.26.0,<1.27.0)"]
+pi = ["mypy-boto3-pi (>=1.26.0,<1.27.0)"]
+pinpoint = ["mypy-boto3-pinpoint (>=1.26.0,<1.27.0)"]
+pinpoint-email = ["mypy-boto3-pinpoint-email (>=1.26.0,<1.27.0)"]
+pinpoint-sms-voice = ["mypy-boto3-pinpoint-sms-voice (>=1.26.0,<1.27.0)"]
+pinpoint-sms-voice-v2 = ["mypy-boto3-pinpoint-sms-voice-v2 (>=1.26.0,<1.27.0)"]
+pipes = ["mypy-boto3-pipes (>=1.26.0,<1.27.0)"]
+polly = ["mypy-boto3-polly (>=1.26.0,<1.27.0)"]
+pricing = ["mypy-boto3-pricing (>=1.26.0,<1.27.0)"]
+privatenetworks = ["mypy-boto3-privatenetworks (>=1.26.0,<1.27.0)"]
+proton = ["mypy-boto3-proton (>=1.26.0,<1.27.0)"]
+qldb = ["mypy-boto3-qldb (>=1.26.0,<1.27.0)"]
+qldb-session = ["mypy-boto3-qldb-session (>=1.26.0,<1.27.0)"]
+quicksight = ["mypy-boto3-quicksight (>=1.26.0,<1.27.0)"]
+ram = ["mypy-boto3-ram (>=1.26.0,<1.27.0)"]
+rbin = ["mypy-boto3-rbin (>=1.26.0,<1.27.0)"]
+rds = ["mypy-boto3-rds (>=1.26.0,<1.27.0)"]
+rds-data = ["mypy-boto3-rds-data (>=1.26.0,<1.27.0)"]
+redshift = ["mypy-boto3-redshift (>=1.26.0,<1.27.0)"]
+redshift-data = ["mypy-boto3-redshift-data (>=1.26.0,<1.27.0)"]
+redshift-serverless = ["mypy-boto3-redshift-serverless (>=1.26.0,<1.27.0)"]
+rekognition = ["mypy-boto3-rekognition (>=1.26.0,<1.27.0)"]
+resiliencehub = ["mypy-boto3-resiliencehub (>=1.26.0,<1.27.0)"]
+resource-explorer-2 = ["mypy-boto3-resource-explorer-2 (>=1.26.0,<1.27.0)"]
+resource-groups = ["mypy-boto3-resource-groups (>=1.26.0,<1.27.0)"]
+resourcegroupstaggingapi = ["mypy-boto3-resourcegroupstaggingapi (>=1.26.0,<1.27.0)"]
+robomaker = ["mypy-boto3-robomaker (>=1.26.0,<1.27.0)"]
+rolesanywhere = ["mypy-boto3-rolesanywhere (>=1.26.0,<1.27.0)"]
+route53 = ["mypy-boto3-route53 (>=1.26.0,<1.27.0)"]
+route53-recovery-cluster = ["mypy-boto3-route53-recovery-cluster (>=1.26.0,<1.27.0)"]
+route53-recovery-control-config = ["mypy-boto3-route53-recovery-control-config (>=1.26.0,<1.27.0)"]
+route53-recovery-readiness = ["mypy-boto3-route53-recovery-readiness (>=1.26.0,<1.27.0)"]
+route53domains = ["mypy-boto3-route53domains (>=1.26.0,<1.27.0)"]
+route53resolver = ["mypy-boto3-route53resolver (>=1.26.0,<1.27.0)"]
+rum = ["mypy-boto3-rum (>=1.26.0,<1.27.0)"]
+s3 = ["mypy-boto3-s3 (>=1.26.0,<1.27.0)"]
+s3control = ["mypy-boto3-s3control (>=1.26.0,<1.27.0)"]
+s3outposts = ["mypy-boto3-s3outposts (>=1.26.0,<1.27.0)"]
+sagemaker = ["mypy-boto3-sagemaker (>=1.26.0,<1.27.0)"]
+sagemaker-a2i-runtime = ["mypy-boto3-sagemaker-a2i-runtime (>=1.26.0,<1.27.0)"]
+sagemaker-edge = ["mypy-boto3-sagemaker-edge (>=1.26.0,<1.27.0)"]
+sagemaker-featurestore-runtime = ["mypy-boto3-sagemaker-featurestore-runtime (>=1.26.0,<1.27.0)"]
+sagemaker-geospatial = ["mypy-boto3-sagemaker-geospatial (>=1.26.0,<1.27.0)"]
+sagemaker-metrics = ["mypy-boto3-sagemaker-metrics (>=1.26.0,<1.27.0)"]
+sagemaker-runtime = ["mypy-boto3-sagemaker-runtime (>=1.26.0,<1.27.0)"]
+savingsplans = ["mypy-boto3-savingsplans (>=1.26.0,<1.27.0)"]
+scheduler = ["mypy-boto3-scheduler (>=1.26.0,<1.27.0)"]
+schemas = ["mypy-boto3-schemas (>=1.26.0,<1.27.0)"]
+sdb = ["mypy-boto3-sdb (>=1.26.0,<1.27.0)"]
+secretsmanager = ["mypy-boto3-secretsmanager (>=1.26.0,<1.27.0)"]
+securityhub = ["mypy-boto3-securityhub (>=1.26.0,<1.27.0)"]
+securitylake = ["mypy-boto3-securitylake (>=1.26.0,<1.27.0)"]
+serverlessrepo = ["mypy-boto3-serverlessrepo (>=1.26.0,<1.27.0)"]
+service-quotas = ["mypy-boto3-service-quotas (>=1.26.0,<1.27.0)"]
+servicecatalog = ["mypy-boto3-servicecatalog (>=1.26.0,<1.27.0)"]
+servicecatalog-appregistry = ["mypy-boto3-servicecatalog-appregistry (>=1.26.0,<1.27.0)"]
+servicediscovery = ["mypy-boto3-servicediscovery (>=1.26.0,<1.27.0)"]
+ses = ["mypy-boto3-ses (>=1.26.0,<1.27.0)"]
+sesv2 = ["mypy-boto3-sesv2 (>=1.26.0,<1.27.0)"]
+shield = ["mypy-boto3-shield (>=1.26.0,<1.27.0)"]
+signer = ["mypy-boto3-signer (>=1.26.0,<1.27.0)"]
+simspaceweaver = ["mypy-boto3-simspaceweaver (>=1.26.0,<1.27.0)"]
+sms = ["mypy-boto3-sms (>=1.26.0,<1.27.0)"]
+sms-voice = ["mypy-boto3-sms-voice (>=1.26.0,<1.27.0)"]
+snow-device-management = ["mypy-boto3-snow-device-management (>=1.26.0,<1.27.0)"]
+snowball = ["mypy-boto3-snowball (>=1.26.0,<1.27.0)"]
+sns = ["mypy-boto3-sns (>=1.26.0,<1.27.0)"]
+sqs = ["mypy-boto3-sqs (>=1.26.0,<1.27.0)"]
+ssm = ["mypy-boto3-ssm (>=1.26.0,<1.27.0)"]
+ssm-contacts = ["mypy-boto3-ssm-contacts (>=1.26.0,<1.27.0)"]
+ssm-incidents = ["mypy-boto3-ssm-incidents (>=1.26.0,<1.27.0)"]
+ssm-sap = ["mypy-boto3-ssm-sap (>=1.26.0,<1.27.0)"]
+sso = ["mypy-boto3-sso (>=1.26.0,<1.27.0)"]
+sso-admin = ["mypy-boto3-sso-admin (>=1.26.0,<1.27.0)"]
+sso-oidc = ["mypy-boto3-sso-oidc (>=1.26.0,<1.27.0)"]
+stepfunctions = ["mypy-boto3-stepfunctions (>=1.26.0,<1.27.0)"]
+storagegateway = ["mypy-boto3-storagegateway (>=1.26.0,<1.27.0)"]
+sts = ["mypy-boto3-sts (>=1.26.0,<1.27.0)"]
+support = ["mypy-boto3-support (>=1.26.0,<1.27.0)"]
+support-app = ["mypy-boto3-support-app (>=1.26.0,<1.27.0)"]
+swf = ["mypy-boto3-swf (>=1.26.0,<1.27.0)"]
+synthetics = ["mypy-boto3-synthetics (>=1.26.0,<1.27.0)"]
+textract = ["mypy-boto3-textract (>=1.26.0,<1.27.0)"]
+timestream-query = ["mypy-boto3-timestream-query (>=1.26.0,<1.27.0)"]
+timestream-write = ["mypy-boto3-timestream-write (>=1.26.0,<1.27.0)"]
+tnb = ["mypy-boto3-tnb (>=1.26.0,<1.27.0)"]
+transcribe = ["mypy-boto3-transcribe (>=1.26.0,<1.27.0)"]
+transfer = ["mypy-boto3-transfer (>=1.26.0,<1.27.0)"]
+translate = ["mypy-boto3-translate (>=1.26.0,<1.27.0)"]
+voice-id = ["mypy-boto3-voice-id (>=1.26.0,<1.27.0)"]
+waf = ["mypy-boto3-waf (>=1.26.0,<1.27.0)"]
+waf-regional = ["mypy-boto3-waf-regional (>=1.26.0,<1.27.0)"]
+wafv2 = ["mypy-boto3-wafv2 (>=1.26.0,<1.27.0)"]
+wellarchitected = ["mypy-boto3-wellarchitected (>=1.26.0,<1.27.0)"]
+wisdom = ["mypy-boto3-wisdom (>=1.26.0,<1.27.0)"]
+workdocs = ["mypy-boto3-workdocs (>=1.26.0,<1.27.0)"]
+worklink = ["mypy-boto3-worklink (>=1.26.0,<1.27.0)"]
+workmail = ["mypy-boto3-workmail (>=1.26.0,<1.27.0)"]
+workmailmessageflow = ["mypy-boto3-workmailmessageflow (>=1.26.0,<1.27.0)"]
+workspaces = ["mypy-boto3-workspaces (>=1.26.0,<1.27.0)"]
+workspaces-web = ["mypy-boto3-workspaces-web (>=1.26.0,<1.27.0)"]
+xray = ["mypy-boto3-xray (>=1.26.0,<1.27.0)"]
+
[[package]]
name = "botocore"
-version = "1.29.112"
+version = "1.29.90"
description = "Low-level, data-driven core of boto 3."
category = "dev"
optional = false
python-versions = ">= 3.7"
files = [
- {file = "botocore-1.29.112-py3-none-any.whl", hash = "sha256:2cbaddb09b46dcb0a05490724d51acb224d3a8df433c347f995b4d78bfb02c8a"},
- {file = "botocore-1.29.112.tar.gz", hash = "sha256:1f52d9371d7b5ee30a53dcef7954c3cf22e04b131cfab5268035f3299ccde9e1"},
+ {file = "botocore-1.29.90-py3-none-any.whl", hash = "sha256:1b8c1b8c366875e65d39237a296842b9c0ea33af2ba4a2771db2ba6aefa663ef"},
+ {file = "botocore-1.29.90.tar.gz", hash = "sha256:2dbbc2c7d93ddefcf9896268597212d446e5d416fbceb1b12c793660fa9f83f3"},
]
[package.dependencies]
@@ -90,28 +481,43 @@ urllib3 = ">=1.25.4,<1.27"
[package.extras]
crt = ["awscrt (==0.16.9)"]
+[[package]]
+name = "botocore-stubs"
+version = "1.29.165"
+description = "Type annotations and code completion for botocore"
+category = "dev"
+optional = false
+python-versions = ">=3.7,<4.0"
+files = [
+ {file = "botocore_stubs-1.29.165-py3-none-any.whl", hash = "sha256:020de306ca1e18263e5a73b9142ec9901080f36d7c302ca53850483955e894ad"},
+ {file = "botocore_stubs-1.29.165.tar.gz", hash = "sha256:e9b23f54137bffbe7dcc08d9ca072172368cf92723aee34ec1de6e665f767c60"},
+]
+
+[package.dependencies]
+types-awscrt = "*"
+
[[package]]
name = "cachetools"
-version = "5.3.0"
+version = "5.3.1"
description = "Extensible memoizing collections and decorators"
category = "dev"
optional = false
-python-versions = "~=3.7"
+python-versions = ">=3.7"
files = [
- {file = "cachetools-5.3.0-py3-none-any.whl", hash = "sha256:429e1a1e845c008ea6c85aa35d4b98b65d6a9763eeef3e37e92728a12d1de9d4"},
- {file = "cachetools-5.3.0.tar.gz", hash = "sha256:13dfddc7b8df938c21a940dfa6557ce6e94a2f1cdfa58eb90c805721d58f2c14"},
+ {file = "cachetools-5.3.1-py3-none-any.whl", hash = "sha256:95ef631eeaea14ba2e36f06437f36463aac3a096799e876ee55e5cdccb102590"},
+ {file = "cachetools-5.3.1.tar.gz", hash = "sha256:dce83f2d9b4e1f732a8cd44af8e8fab2dbe46201467fc98b3ef8f269092bf62b"},
]
[[package]]
name = "certifi"
-version = "2022.12.7"
+version = "2023.5.7"
description = "Python package for providing Mozilla's CA Bundle."
category = "main"
optional = false
python-versions = ">=3.6"
files = [
- {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"},
- {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"},
+ {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"},
+ {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"},
]
[[package]]
@@ -195,7 +601,7 @@ pycparser = "*"
name = "chardet"
version = "5.1.0"
description = "Universal encoding detector for Python 3"
-category = "main"
+category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -205,99 +611,99 @@ files = [
[[package]]
name = "charset-normalizer"
-version = "3.1.0"
+version = "3.2.0"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
category = "main"
optional = false
python-versions = ">=3.7.0"
files = [
- {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"},
- {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"},
+ {file = "charset-normalizer-3.2.0.tar.gz", hash = "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-win32.whl", hash = "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-win32.whl", hash = "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-win32.whl", hash = "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-win32.whl", hash = "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-win32.whl", hash = "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80"},
+ {file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"},
]
[[package]]
name = "click"
-version = "8.1.3"
+version = "8.1.4"
description = "Composable command line interface toolkit"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
- {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
+ {file = "click-8.1.4-py3-none-any.whl", hash = "sha256:2739815aaa5d2c986a88f1e9230c55e17f0caad3d958a5e13ad0797c166db9e3"},
+ {file = "click-8.1.4.tar.gz", hash = "sha256:b97d0c74955da062a7d4ef92fadb583806a585b2ea81958a81bd72726cbb8e37"},
]
[package.dependencies]
@@ -317,63 +723,72 @@ files = [
[[package]]
name = "coverage"
-version = "7.2.3"
+version = "7.2.7"
description = "Code coverage measurement for Python"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "coverage-7.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e58c0d41d336569d63d1b113bd573db8363bc4146f39444125b7f8060e4e04f5"},
- {file = "coverage-7.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:344e714bd0fe921fc72d97404ebbdbf9127bac0ca1ff66d7b79efc143cf7c0c4"},
- {file = "coverage-7.2.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:974bc90d6f6c1e59ceb1516ab00cf1cdfbb2e555795d49fa9571d611f449bcb2"},
- {file = "coverage-7.2.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0743b0035d4b0e32bc1df5de70fba3059662ace5b9a2a86a9f894cfe66569013"},
- {file = "coverage-7.2.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d0391fb4cfc171ce40437f67eb050a340fdbd0f9f49d6353a387f1b7f9dd4fa"},
- {file = "coverage-7.2.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a42e1eff0ca9a7cb7dc9ecda41dfc7cbc17cb1d02117214be0561bd1134772b"},
- {file = "coverage-7.2.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:be19931a8dcbe6ab464f3339966856996b12a00f9fe53f346ab3be872d03e257"},
- {file = "coverage-7.2.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:72fcae5bcac3333a4cf3b8f34eec99cea1187acd55af723bcbd559adfdcb5535"},
- {file = "coverage-7.2.3-cp310-cp310-win32.whl", hash = "sha256:aeae2aa38395b18106e552833f2a50c27ea0000122bde421c31d11ed7e6f9c91"},
- {file = "coverage-7.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:83957d349838a636e768251c7e9979e899a569794b44c3728eaebd11d848e58e"},
- {file = "coverage-7.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dfd393094cd82ceb9b40df4c77976015a314b267d498268a076e940fe7be6b79"},
- {file = "coverage-7.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:182eb9ac3f2b4874a1f41b78b87db20b66da6b9cdc32737fbbf4fea0c35b23fc"},
- {file = "coverage-7.2.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bb1e77a9a311346294621be905ea8a2c30d3ad371fc15bb72e98bfcfae532df"},
- {file = "coverage-7.2.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca0f34363e2634deffd390a0fef1aa99168ae9ed2af01af4a1f5865e362f8623"},
- {file = "coverage-7.2.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55416d7385774285b6e2a5feca0af9652f7f444a4fa3d29d8ab052fafef9d00d"},
- {file = "coverage-7.2.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:06ddd9c0249a0546997fdda5a30fbcb40f23926df0a874a60a8a185bc3a87d93"},
- {file = "coverage-7.2.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fff5aaa6becf2c6a1699ae6a39e2e6fb0672c2d42eca8eb0cafa91cf2e9bd312"},
- {file = "coverage-7.2.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ea53151d87c52e98133eb8ac78f1206498c015849662ca8dc246255265d9c3c4"},
- {file = "coverage-7.2.3-cp311-cp311-win32.whl", hash = "sha256:8f6c930fd70d91ddee53194e93029e3ef2aabe26725aa3c2753df057e296b925"},
- {file = "coverage-7.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:fa546d66639d69aa967bf08156eb8c9d0cd6f6de84be9e8c9819f52ad499c910"},
- {file = "coverage-7.2.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b2317d5ed777bf5a033e83d4f1389fd4ef045763141d8f10eb09a7035cee774c"},
- {file = "coverage-7.2.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be9824c1c874b73b96288c6d3de793bf7f3a597770205068c6163ea1f326e8b9"},
- {file = "coverage-7.2.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2c3b2803e730dc2797a017335827e9da6da0e84c745ce0f552e66400abdfb9a1"},
- {file = "coverage-7.2.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f69770f5ca1994cb32c38965e95f57504d3aea96b6c024624fdd5bb1aa494a1"},
- {file = "coverage-7.2.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1127b16220f7bfb3f1049ed4a62d26d81970a723544e8252db0efde853268e21"},
- {file = "coverage-7.2.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:aa784405f0c640940595fa0f14064d8e84aff0b0f762fa18393e2760a2cf5841"},
- {file = "coverage-7.2.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3146b8e16fa60427e03884301bf8209221f5761ac754ee6b267642a2fd354c48"},
- {file = "coverage-7.2.3-cp37-cp37m-win32.whl", hash = "sha256:1fd78b911aea9cec3b7e1e2622c8018d51c0d2bbcf8faaf53c2497eb114911c1"},
- {file = "coverage-7.2.3-cp37-cp37m-win_amd64.whl", hash = "sha256:0f3736a5d34e091b0a611964c6262fd68ca4363df56185902528f0b75dbb9c1f"},
- {file = "coverage-7.2.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:981b4df72c93e3bc04478153df516d385317628bd9c10be699c93c26ddcca8ab"},
- {file = "coverage-7.2.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c0045f8f23a5fb30b2eb3b8a83664d8dc4fb58faddf8155d7109166adb9f2040"},
- {file = "coverage-7.2.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f760073fcf8f3d6933178d67754f4f2d4e924e321f4bb0dcef0424ca0215eba1"},
- {file = "coverage-7.2.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c86bd45d1659b1ae3d0ba1909326b03598affbc9ed71520e0ff8c31a993ad911"},
- {file = "coverage-7.2.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:172db976ae6327ed4728e2507daf8a4de73c7cc89796483e0a9198fd2e47b462"},
- {file = "coverage-7.2.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d2a3a6146fe9319926e1d477842ca2a63fe99af5ae690b1f5c11e6af074a6b5c"},
- {file = "coverage-7.2.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:f649dd53833b495c3ebd04d6eec58479454a1784987af8afb77540d6c1767abd"},
- {file = "coverage-7.2.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7c4ed4e9f3b123aa403ab424430b426a1992e6f4c8fd3cb56ea520446e04d152"},
- {file = "coverage-7.2.3-cp38-cp38-win32.whl", hash = "sha256:eb0edc3ce9760d2f21637766c3aa04822030e7451981ce569a1b3456b7053f22"},
- {file = "coverage-7.2.3-cp38-cp38-win_amd64.whl", hash = "sha256:63cdeaac4ae85a179a8d6bc09b77b564c096250d759eed343a89d91bce8b6367"},
- {file = "coverage-7.2.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:20d1a2a76bb4eb00e4d36b9699f9b7aba93271c9c29220ad4c6a9581a0320235"},
- {file = "coverage-7.2.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ea748802cc0de4de92ef8244dd84ffd793bd2e7be784cd8394d557a3c751e21"},
- {file = "coverage-7.2.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21b154aba06df42e4b96fc915512ab39595105f6c483991287021ed95776d934"},
- {file = "coverage-7.2.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd214917cabdd6f673a29d708574e9fbdb892cb77eb426d0eae3490d95ca7859"},
- {file = "coverage-7.2.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c2e58e45fe53fab81f85474e5d4d226eeab0f27b45aa062856c89389da2f0d9"},
- {file = "coverage-7.2.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:87ecc7c9a1a9f912e306997ffee020297ccb5ea388421fe62a2a02747e4d5539"},
- {file = "coverage-7.2.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:387065e420aed3c71b61af7e82c7b6bc1c592f7e3c7a66e9f78dd178699da4fe"},
- {file = "coverage-7.2.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ea3f5bc91d7d457da7d48c7a732beaf79d0c8131df3ab278e6bba6297e23c6c4"},
- {file = "coverage-7.2.3-cp39-cp39-win32.whl", hash = "sha256:ae7863a1d8db6a014b6f2ff9c1582ab1aad55a6d25bac19710a8df68921b6e30"},
- {file = "coverage-7.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:3f04becd4fcda03c0160d0da9c8f0c246bc78f2f7af0feea1ec0930e7c93fa4a"},
- {file = "coverage-7.2.3-pp37.pp38.pp39-none-any.whl", hash = "sha256:965ee3e782c7892befc25575fa171b521d33798132692df428a09efacaffe8d0"},
- {file = "coverage-7.2.3.tar.gz", hash = "sha256:d298c2815fa4891edd9abe5ad6e6cb4207104c7dd9fd13aea3fdebf6f9b91259"},
+ {file = "coverage-7.2.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d39b5b4f2a66ccae8b7263ac3c8170994b65266797fb96cbbfd3fb5b23921db8"},
+ {file = "coverage-7.2.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d040ef7c9859bb11dfeb056ff5b3872436e3b5e401817d87a31e1750b9ae2fb"},
+ {file = "coverage-7.2.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba90a9563ba44a72fda2e85302c3abc71c5589cea608ca16c22b9804262aaeb6"},
+ {file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7d9405291c6928619403db1d10bd07888888ec1abcbd9748fdaa971d7d661b2"},
+ {file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31563e97dae5598556600466ad9beea39fb04e0229e61c12eaa206e0aa202063"},
+ {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ebba1cd308ef115925421d3e6a586e655ca5a77b5bf41e02eb0e4562a111f2d1"},
+ {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cb017fd1b2603ef59e374ba2063f593abe0fc45f2ad9abdde5b4d83bd922a353"},
+ {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62a5c7dad11015c66fbb9d881bc4caa5b12f16292f857842d9d1871595f4495"},
+ {file = "coverage-7.2.7-cp310-cp310-win32.whl", hash = "sha256:ee57190f24fba796e36bb6d3aa8a8783c643d8fa9760c89f7a98ab5455fbf818"},
+ {file = "coverage-7.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850"},
+ {file = "coverage-7.2.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f"},
+ {file = "coverage-7.2.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5baa06420f837184130752b7c5ea0808762083bf3487b5038d68b012e5937dbe"},
+ {file = "coverage-7.2.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3"},
+ {file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52edc1a60c0d34afa421c9c37078817b2e67a392cab17d97283b64c5833f427f"},
+ {file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63426706118b7f5cf6bb6c895dc215d8a418d5952544042c8a2d9fe87fcf09cb"},
+ {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:afb17f84d56068a7c29f5fa37bfd38d5aba69e3304af08ee94da8ed5b0865833"},
+ {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:48c19d2159d433ccc99e729ceae7d5293fbffa0bdb94952d3579983d1c8c9d97"},
+ {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0e1f928eaf5469c11e886fe0885ad2bf1ec606434e79842a879277895a50942a"},
+ {file = "coverage-7.2.7-cp311-cp311-win32.whl", hash = "sha256:33d6d3ea29d5b3a1a632b3c4e4f4ecae24ef170b0b9ee493883f2df10039959a"},
+ {file = "coverage-7.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:5b7540161790b2f28143191f5f8ec02fb132660ff175b7747b95dcb77ac26562"},
+ {file = "coverage-7.2.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f2f67fe12b22cd130d34d0ef79206061bfb5eda52feb6ce0dba0644e20a03cf4"},
+ {file = "coverage-7.2.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a342242fe22407f3c17f4b499276a02b01e80f861f1682ad1d95b04018e0c0d4"},
+ {file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:171717c7cb6b453aebac9a2ef603699da237f341b38eebfee9be75d27dc38e01"},
+ {file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49969a9f7ffa086d973d91cec8d2e31080436ef0fb4a359cae927e742abfaaa6"},
+ {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b46517c02ccd08092f4fa99f24c3b83d8f92f739b4657b0f146246a0ca6a831d"},
+ {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a3d33a6b3eae87ceaefa91ffdc130b5e8536182cd6dfdbfc1aa56b46ff8c86de"},
+ {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d"},
+ {file = "coverage-7.2.7-cp312-cp312-win32.whl", hash = "sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511"},
+ {file = "coverage-7.2.7-cp312-cp312-win_amd64.whl", hash = "sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3"},
+ {file = "coverage-7.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58c2ccc2f00ecb51253cbe5d8d7122a34590fac9646a960d1430d5b15321d95f"},
+ {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d22656368f0e6189e24722214ed8d66b8022db19d182927b9a248a2a8a2f67eb"},
+ {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a895fcc7b15c3fc72beb43cdcbdf0ddb7d2ebc959edac9cef390b0d14f39f8a9"},
+ {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84606b74eb7de6ff581a7915e2dab7a28a0517fbe1c9239eb227e1354064dcd"},
+ {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0a5f9e1dbd7fbe30196578ca36f3fba75376fb99888c395c5880b355e2875f8a"},
+ {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:419bfd2caae268623dd469eff96d510a920c90928b60f2073d79f8fe2bbc5959"},
+ {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2aee274c46590717f38ae5e4650988d1af340fe06167546cc32fe2f58ed05b02"},
+ {file = "coverage-7.2.7-cp37-cp37m-win32.whl", hash = "sha256:61b9a528fb348373c433e8966535074b802c7a5d7f23c4f421e6c6e2f1697a6f"},
+ {file = "coverage-7.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:b1c546aca0ca4d028901d825015dc8e4d56aac4b541877690eb76490f1dc8ed0"},
+ {file = "coverage-7.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:54b896376ab563bd38453cecb813c295cf347cf5906e8b41d340b0321a5433e5"},
+ {file = "coverage-7.2.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3d376df58cc111dc8e21e3b6e24606b5bb5dee6024f46a5abca99124b2229ef5"},
+ {file = "coverage-7.2.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e330fc79bd7207e46c7d7fd2bb4af2963f5f635703925543a70b99574b0fea9"},
+ {file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e9d683426464e4a252bf70c3498756055016f99ddaec3774bf368e76bbe02b6"},
+ {file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d13c64ee2d33eccf7437961b6ea7ad8673e2be040b4f7fd4fd4d4d28d9ccb1e"},
+ {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7aa5f8a41217360e600da646004f878250a0d6738bcdc11a0a39928d7dc2050"},
+ {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fa03bce9bfbeeef9f3b160a8bed39a221d82308b4152b27d82d8daa7041fee5"},
+ {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:245167dd26180ab4c91d5e1496a30be4cd721a5cf2abf52974f965f10f11419f"},
+ {file = "coverage-7.2.7-cp38-cp38-win32.whl", hash = "sha256:d2c2db7fd82e9b72937969bceac4d6ca89660db0a0967614ce2481e81a0b771e"},
+ {file = "coverage-7.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:2e07b54284e381531c87f785f613b833569c14ecacdcb85d56b25c4622c16c3c"},
+ {file = "coverage-7.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9"},
+ {file = "coverage-7.2.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2"},
+ {file = "coverage-7.2.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7"},
+ {file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6951407391b639504e3b3be51b7ba5f3528adbf1a8ac3302b687ecababf929e"},
+ {file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f48351d66575f535669306aa7d6d6f71bc43372473b54a832222803eb956fd1"},
+ {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b29019c76039dc3c0fd815c41392a044ce555d9bcdd38b0fb60fb4cd8e475ba9"},
+ {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:81c13a1fc7468c40f13420732805a4c38a105d89848b7c10af65a90beff25250"},
+ {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:975d70ab7e3c80a3fe86001d8751f6778905ec723f5b110aed1e450da9d4b7f2"},
+ {file = "coverage-7.2.7-cp39-cp39-win32.whl", hash = "sha256:7ee7d9d4822c8acc74a5e26c50604dff824710bc8de424904c0982e25c39c6cb"},
+ {file = "coverage-7.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:eb393e5ebc85245347950143969b241d08b52b88a3dc39479822e073a1a8eb27"},
+ {file = "coverage-7.2.7-pp37.pp38.pp39-none-any.whl", hash = "sha256:b7b4c971f05e6ae490fef852c218b0e79d4e52f79ef0c8475566584a8fb3e01d"},
+ {file = "coverage-7.2.7.tar.gz", hash = "sha256:924d94291ca674905fe9481f12294eb11f2d3d3fd1adb20314ba89e94f44ed59"},
]
[package.dependencies]
@@ -384,31 +799,35 @@ toml = ["tomli"]
[[package]]
name = "cryptography"
-version = "40.0.1"
+version = "41.0.2"
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
category = "dev"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
files = [
- {file = "cryptography-40.0.1-cp36-abi3-macosx_10_12_universal2.whl", hash = "sha256:918cb89086c7d98b1b86b9fdb70c712e5a9325ba6f7d7cfb509e784e0cfc6917"},
- {file = "cryptography-40.0.1-cp36-abi3-macosx_10_12_x86_64.whl", hash = "sha256:9618a87212cb5200500e304e43691111570e1f10ec3f35569fdfcd17e28fd797"},
- {file = "cryptography-40.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a4805a4ca729d65570a1b7cac84eac1e431085d40387b7d3bbaa47e39890b88"},
- {file = "cryptography-40.0.1-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63dac2d25c47f12a7b8aa60e528bfb3c51c5a6c5a9f7c86987909c6c79765554"},
- {file = "cryptography-40.0.1-cp36-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:0a4e3406cfed6b1f6d6e87ed243363652b2586b2d917b0609ca4f97072994405"},
- {file = "cryptography-40.0.1-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1e0af458515d5e4028aad75f3bb3fe7a31e46ad920648cd59b64d3da842e4356"},
- {file = "cryptography-40.0.1-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:d8aa3609d337ad85e4eb9bb0f8bcf6e4409bfb86e706efa9a027912169e89122"},
- {file = "cryptography-40.0.1-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:cf91e428c51ef692b82ce786583e214f58392399cf65c341bc7301d096fa3ba2"},
- {file = "cryptography-40.0.1-cp36-abi3-win32.whl", hash = "sha256:650883cc064297ef3676b1db1b7b1df6081794c4ada96fa457253c4cc40f97db"},
- {file = "cryptography-40.0.1-cp36-abi3-win_amd64.whl", hash = "sha256:a805a7bce4a77d51696410005b3e85ae2839bad9aa38894afc0aa99d8e0c3160"},
- {file = "cryptography-40.0.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cd033d74067d8928ef00a6b1327c8ea0452523967ca4463666eeba65ca350d4c"},
- {file = "cryptography-40.0.1-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d36bbeb99704aabefdca5aee4eba04455d7a27ceabd16f3b3ba9bdcc31da86c4"},
- {file = "cryptography-40.0.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:32057d3d0ab7d4453778367ca43e99ddb711770477c4f072a51b3ca69602780a"},
- {file = "cryptography-40.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:f5d7b79fa56bc29580faafc2ff736ce05ba31feaa9d4735048b0de7d9ceb2b94"},
- {file = "cryptography-40.0.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7c872413353c70e0263a9368c4993710070e70ab3e5318d85510cc91cce77e7c"},
- {file = "cryptography-40.0.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:28d63d75bf7ae4045b10de5413fb1d6338616e79015999ad9cf6fc538f772d41"},
- {file = "cryptography-40.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6f2bbd72f717ce33100e6467572abaedc61f1acb87b8d546001328d7f466b778"},
- {file = "cryptography-40.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:cc3a621076d824d75ab1e1e530e66e7e8564e357dd723f2533225d40fe35c60c"},
- {file = "cryptography-40.0.1.tar.gz", hash = "sha256:2803f2f8b1e95f614419926c7e6f55d828afc614ca5ed61543877ae668cc3472"},
+ {file = "cryptography-41.0.2-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:01f1d9e537f9a15b037d5d9ee442b8c22e3ae11ce65ea1f3316a41c78756b711"},
+ {file = "cryptography-41.0.2-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:079347de771f9282fbfe0e0236c716686950c19dee1b76240ab09ce1624d76d7"},
+ {file = "cryptography-41.0.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:439c3cc4c0d42fa999b83ded80a9a1fb54d53c58d6e59234cfe97f241e6c781d"},
+ {file = "cryptography-41.0.2-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f14ad275364c8b4e525d018f6716537ae7b6d369c094805cae45300847e0894f"},
+ {file = "cryptography-41.0.2-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:84609ade00a6ec59a89729e87a503c6e36af98ddcd566d5f3be52e29ba993182"},
+ {file = "cryptography-41.0.2-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:49c3222bb8f8e800aead2e376cbef687bc9e3cb9b58b29a261210456a7783d83"},
+ {file = "cryptography-41.0.2-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:d73f419a56d74fef257955f51b18d046f3506270a5fd2ac5febbfa259d6c0fa5"},
+ {file = "cryptography-41.0.2-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:2a034bf7d9ca894720f2ec1d8b7b5832d7e363571828037f9e0c4f18c1b58a58"},
+ {file = "cryptography-41.0.2-cp37-abi3-win32.whl", hash = "sha256:d124682c7a23c9764e54ca9ab5b308b14b18eba02722b8659fb238546de83a76"},
+ {file = "cryptography-41.0.2-cp37-abi3-win_amd64.whl", hash = "sha256:9c3fe6534d59d071ee82081ca3d71eed3210f76ebd0361798c74abc2bcf347d4"},
+ {file = "cryptography-41.0.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a719399b99377b218dac6cf547b6ec54e6ef20207b6165126a280b0ce97e0d2a"},
+ {file = "cryptography-41.0.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:182be4171f9332b6741ee818ec27daff9fb00349f706629f5cbf417bd50e66fd"},
+ {file = "cryptography-41.0.2-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:7a9a3bced53b7f09da251685224d6a260c3cb291768f54954e28f03ef14e3766"},
+ {file = "cryptography-41.0.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:f0dc40e6f7aa37af01aba07277d3d64d5a03dc66d682097541ec4da03cc140ee"},
+ {file = "cryptography-41.0.2-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:674b669d5daa64206c38e507808aae49904c988fa0a71c935e7006a3e1e83831"},
+ {file = "cryptography-41.0.2-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:7af244b012711a26196450d34f483357e42aeddb04128885d95a69bd8b14b69b"},
+ {file = "cryptography-41.0.2-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9b6d717393dbae53d4e52684ef4f022444fc1cce3c48c38cb74fca29e1f08eaa"},
+ {file = "cryptography-41.0.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:192255f539d7a89f2102d07d7375b1e0a81f7478925b3bc2e0549ebf739dae0e"},
+ {file = "cryptography-41.0.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f772610fe364372de33d76edcd313636a25684edb94cee53fd790195f5989d14"},
+ {file = "cryptography-41.0.2-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:b332cba64d99a70c1e0836902720887fb4529ea49ea7f5462cf6640e095e11d2"},
+ {file = "cryptography-41.0.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9a6673c1828db6270b76b22cc696f40cde9043eb90373da5c2f8f2158957f42f"},
+ {file = "cryptography-41.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:342f3767e25876751e14f8459ad85e77e660537ca0a066e10e75df9c9e9099f0"},
+ {file = "cryptography-41.0.2.tar.gz", hash = "sha256:7d230bf856164de164ecb615ccc14c7fc6de6906ddd5b491f3af90d3514c925c"},
]
[package.dependencies]
@@ -417,12 +836,12 @@ cffi = ">=1.12"
[package.extras]
docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"]
docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"]
-pep8test = ["black", "check-manifest", "mypy", "ruff"]
-sdist = ["setuptools-rust (>=0.11.4)"]
+nox = ["nox"]
+pep8test = ["black", "check-sdist", "mypy", "ruff"]
+sdist = ["build"]
ssh = ["bcrypt (>=3.1.5)"]
-test = ["iso8601", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-shard (>=0.1.2)", "pytest-subtests", "pytest-xdist"]
+test = ["pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"]
test-randomorder = ["pytest-randomly"]
-tox = ["tox"]
[[package]]
name = "distlib"
@@ -436,52 +855,124 @@ files = [
{file = "distlib-0.3.6.tar.gz", hash = "sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46"},
]
+[[package]]
+name = "docker"
+version = "6.1.3"
+description = "A Python library for the Docker Engine API."
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "docker-6.1.3-py3-none-any.whl", hash = "sha256:aecd2277b8bf8e506e484f6ab7aec39abe0038e29fa4a6d3ba86c3fe01844ed9"},
+ {file = "docker-6.1.3.tar.gz", hash = "sha256:aa6d17830045ba5ef0168d5eaa34d37beeb113948c413affe1d5991fc11f9a20"},
+]
+
+[package.dependencies]
+packaging = ">=14.0"
+pywin32 = {version = ">=304", markers = "sys_platform == \"win32\""}
+requests = ">=2.26.0"
+urllib3 = ">=1.26.0"
+websocket-client = ">=0.32.0"
+
+[package.extras]
+ssh = ["paramiko (>=2.4.3)"]
+
+[[package]]
+name = "ecdsa"
+version = "0.18.0"
+description = "ECDSA cryptographic signature library (pure python)"
+category = "dev"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+files = [
+ {file = "ecdsa-0.18.0-py2.py3-none-any.whl", hash = "sha256:80600258e7ed2f16b9aa1d7c295bd70194109ad5a30fdee0eaeefef1d4c559dd"},
+ {file = "ecdsa-0.18.0.tar.gz", hash = "sha256:190348041559e21b22a1d65cee485282ca11a6f81d503fddb84d5017e9ed1e49"},
+]
+
+[package.dependencies]
+six = ">=1.9.0"
+
+[package.extras]
+gmpy = ["gmpy"]
+gmpy2 = ["gmpy2"]
+
[[package]]
name = "exceptiongroup"
-version = "1.1.1"
+version = "1.1.2"
description = "Backport of PEP 654 (exception groups)"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"},
- {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"},
+ {file = "exceptiongroup-1.1.2-py3-none-any.whl", hash = "sha256:e346e69d186172ca7cf029c8c1d16235aa0e04035e5750b4b95039e65204328f"},
+ {file = "exceptiongroup-1.1.2.tar.gz", hash = "sha256:12c3e887d6485d16943a309616de20ae5582633e0a2eda17f4e10fd61c1e8af5"},
]
[package.extras]
test = ["pytest (>=6)"]
+[[package]]
+name = "execnet"
+version = "2.0.2"
+description = "execnet: rapid multi-Python deployment"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "execnet-2.0.2-py3-none-any.whl", hash = "sha256:88256416ae766bc9e8895c76a87928c0012183da3cc4fc18016e6f050e025f41"},
+ {file = "execnet-2.0.2.tar.gz", hash = "sha256:cc59bc4423742fd71ad227122eb0dd44db51efb3dc4095b45ac9a08c770096af"},
+]
+
+[package.extras]
+testing = ["hatch", "pre-commit", "pytest", "tox"]
+
[[package]]
name = "filelock"
-version = "3.11.0"
+version = "3.12.2"
description = "A platform independent file lock."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "filelock-3.11.0-py3-none-any.whl", hash = "sha256:f08a52314748335c6460fc8fe40cd5638b85001225db78c2aa01c8c0db83b318"},
- {file = "filelock-3.11.0.tar.gz", hash = "sha256:3618c0da67adcc0506b015fd11ef7faf1b493f0b40d87728e19986b536890c37"},
+ {file = "filelock-3.12.2-py3-none-any.whl", hash = "sha256:cbb791cdea2a72f23da6ac5b5269ab0a0d161e9ef0100e653b69049a7706d1ec"},
+ {file = "filelock-3.12.2.tar.gz", hash = "sha256:002740518d8aa59a26b0c76e10fb8c6e15eae825d34b6fdf670333fd7b938d81"},
]
[package.extras]
-docs = ["furo (>=2023.3.27)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"]
-testing = ["covdefaults (>=2.3)", "coverage (>=7.2.2)", "diff-cover (>=7.5)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"]
+docs = ["furo (>=2023.5.20)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
+testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"]
+
+[[package]]
+name = "flake8"
+version = "6.0.0"
+description = "the modular source code checker: pep8 pyflakes and co"
+category = "dev"
+optional = false
+python-versions = ">=3.8.1"
+files = [
+ {file = "flake8-6.0.0-py2.py3-none-any.whl", hash = "sha256:3833794e27ff64ea4e9cf5d410082a8b97ff1a06c16aa3d2027339cd0f1195c7"},
+ {file = "flake8-6.0.0.tar.gz", hash = "sha256:c61007e76655af75e6785a931f452915b371dc48f56efd765247c8fe68f2b181"},
+]
+
+[package.dependencies]
+mccabe = ">=0.7.0,<0.8.0"
+pycodestyle = ">=2.10.0,<2.11.0"
+pyflakes = ">=3.0.0,<3.1.0"
[[package]]
name = "freezegun"
-version = "0.3.15"
+version = "1.2.2"
description = "Let your Python tests travel through time"
category = "dev"
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+python-versions = ">=3.6"
files = [
- {file = "freezegun-0.3.15-py2.py3-none-any.whl", hash = "sha256:82c757a05b7c7ca3e176bfebd7d6779fd9139c7cb4ef969c38a28d74deef89b2"},
- {file = "freezegun-0.3.15.tar.gz", hash = "sha256:e2062f2c7f95cc276a834c22f1a17179467176b624cc6f936e8bc3be5535ad1b"},
+ {file = "freezegun-1.2.2-py3-none-any.whl", hash = "sha256:ea1b963b993cb9ea195adbd893a48d573fda951b0da64f60883d7e988b606c9f"},
+ {file = "freezegun-1.2.2.tar.gz", hash = "sha256:cd22d1ba06941384410cd967d8a99d5ae2442f57dfafeff2fda5de8dc5c05446"},
]
[package.dependencies]
-python-dateutil = ">=1.0,<2.0 || >2.0"
-six = "*"
+python-dateutil = ">=2.7"
[[package]]
name = "idna"
@@ -507,6 +998,24 @@ files = [
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
]
+[[package]]
+name = "isort"
+version = "5.12.0"
+description = "A Python utility / library to sort Python imports."
+category = "dev"
+optional = false
+python-versions = ">=3.8.0"
+files = [
+ {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"},
+ {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"},
+]
+
+[package.extras]
+colors = ["colorama (>=0.4.3)"]
+pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"]
+plugins = ["setuptools"]
+requirements-deprecated-finder = ["pip-api", "pipreqs"]
+
[[package]]
name = "jinja2"
version = "3.1.2"
@@ -539,119 +1048,115 @@ files = [
[[package]]
name = "markupsafe"
-version = "2.1.2"
+version = "2.1.3"
description = "Safely add untrusted strings to HTML/XML markup."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-win32.whl", hash = "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603"},
- {file = "MarkupSafe-2.1.2-cp310-cp310-win_amd64.whl", hash = "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-win32.whl", hash = "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625"},
- {file = "MarkupSafe-2.1.2-cp311-cp311-win_amd64.whl", hash = "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-win32.whl", hash = "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859"},
- {file = "MarkupSafe-2.1.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-win32.whl", hash = "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2"},
- {file = "MarkupSafe-2.1.2-cp38-cp38-win_amd64.whl", hash = "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-win32.whl", hash = "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7"},
- {file = "MarkupSafe-2.1.2-cp39-cp39-win_amd64.whl", hash = "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed"},
- {file = "MarkupSafe-2.1.2.tar.gz", hash = "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d"},
-]
-
-[[package]]
-name = "mock"
-version = "2.0.0"
-description = "Rolling backport of unittest.mock for all Pythons"
+ {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"},
+ {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"},
+]
+
+[[package]]
+name = "mccabe"
+version = "0.7.0"
+description = "McCabe checker, plugin for flake8"
category = "dev"
optional = false
-python-versions = "*"
+python-versions = ">=3.6"
files = [
- {file = "mock-2.0.0-py2.py3-none-any.whl", hash = "sha256:5ce3c71c5545b472da17b72268978914d0252980348636840bd34a00b5cc96c1"},
- {file = "mock-2.0.0.tar.gz", hash = "sha256:b158b6df76edd239b8208d481dc46b6afd45a846b7812ff0ce58971cf5bc8bba"},
+ {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"},
+ {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"},
]
-[package.dependencies]
-pbr = ">=0.11"
-six = ">=1.9"
-
-[package.extras]
-docs = ["Pygments (<2)", "jinja2 (<2.7)", "sphinx", "sphinx (<1.3)"]
-test = ["unittest2 (>=1.1.0)"]
-
[[package]]
name = "moto"
-version = "4.1.7"
+version = "4.1.12"
description = ""
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "moto-4.1.7-py2.py3-none-any.whl", hash = "sha256:56de986179f79920f59243bc532e03a7039d24a5ee5aec2eb3b666dcd23d6262"},
- {file = "moto-4.1.7.tar.gz", hash = "sha256:fb9a7615f744da4ea7f154ff8e79782b19781344a6356ca4c0d6217c1237d379"},
+ {file = "moto-4.1.12-py2.py3-none-any.whl", hash = "sha256:6f40141ff2f3a309c19faa169433afdf48d28733d328b08a843021ae36f005d9"},
+ {file = "moto-4.1.12.tar.gz", hash = "sha256:25577e4cf55f05235f4efe78bcfeb5a7704fb75c16b426a5de2fc1e6b7b8545b"},
]
[package.dependencies]
boto3 = ">=1.9.201"
botocore = ">=1.12.201"
cryptography = ">=3.3.1"
+docker = {version = ">=3.0.0", optional = true, markers = "extra == \"dynamodb\""}
Jinja2 = ">=2.10.1"
+py-partiql-parser = {version = "0.3.3", optional = true, markers = "extra == \"dynamodb\""}
python-dateutil = ">=2.1,<3.0.0"
+PyYAML = {version = ">=5.1", optional = true, markers = "extra == \"ssm\""}
requests = ">=2.5"
responses = ">=0.13.0"
+sshpubkeys = {version = ">=3.1.0", optional = true, markers = "extra == \"ec2\""}
werkzeug = ">=0.5,<2.2.0 || >2.2.0,<2.2.1 || >2.2.1"
xmltodict = "*"
[package.extras]
-all = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "graphql-core", "jsondiff (>=1.1.2)", "openapi-spec-validator (>=0.2.8)", "py-partiql-parser (==0.1.0)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"]
+all = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "graphql-core", "jsondiff (>=1.1.2)", "openapi-spec-validator (>=0.2.8)", "py-partiql-parser (==0.3.3)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"]
apigateway = ["PyYAML (>=5.1)", "ecdsa (!=0.15)", "openapi-spec-validator (>=0.2.8)", "python-jose[cryptography] (>=3.1.0,<4.0.0)"]
apigatewayv2 = ["PyYAML (>=5.1)"]
appsync = ["graphql-core"]
awslambda = ["docker (>=3.0.0)"]
batch = ["docker (>=3.0.0)"]
-cloudformation = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "graphql-core", "jsondiff (>=1.1.2)", "openapi-spec-validator (>=0.2.8)", "py-partiql-parser (==0.1.0)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"]
+cloudformation = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "graphql-core", "jsondiff (>=1.1.2)", "openapi-spec-validator (>=0.2.8)", "py-partiql-parser (==0.3.3)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"]
cognitoidp = ["ecdsa (!=0.15)", "python-jose[cryptography] (>=3.1.0,<4.0.0)"]
ds = ["sshpubkeys (>=3.1.0)"]
-dynamodb = ["docker (>=3.0.0)"]
-dynamodbstreams = ["docker (>=3.0.0)"]
+dynamodb = ["docker (>=3.0.0)", "py-partiql-parser (==0.3.3)"]
+dynamodbstreams = ["docker (>=3.0.0)", "py-partiql-parser (==0.3.3)"]
ebs = ["sshpubkeys (>=3.1.0)"]
ec2 = ["sshpubkeys (>=3.1.0)"]
efs = ["sshpubkeys (>=3.1.0)"]
@@ -659,11 +1164,184 @@ eks = ["sshpubkeys (>=3.1.0)"]
glue = ["pyparsing (>=3.0.7)"]
iotdata = ["jsondiff (>=1.1.2)"]
route53resolver = ["sshpubkeys (>=3.1.0)"]
-s3 = ["PyYAML (>=5.1)", "py-partiql-parser (==0.1.0)"]
-server = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "flask (!=2.2.0,!=2.2.1)", "flask-cors", "graphql-core", "jsondiff (>=1.1.2)", "openapi-spec-validator (>=0.2.8)", "py-partiql-parser (==0.1.0)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"]
+s3 = ["PyYAML (>=5.1)", "py-partiql-parser (==0.3.3)"]
+server = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "flask (!=2.2.0,!=2.2.1)", "flask-cors", "graphql-core", "jsondiff (>=1.1.2)", "openapi-spec-validator (>=0.2.8)", "py-partiql-parser (==0.3.3)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"]
ssm = ["PyYAML (>=5.1)"]
xray = ["aws-xray-sdk (>=0.93,!=0.96)", "setuptools"]
+[[package]]
+name = "mypy"
+version = "1.4.1"
+description = "Optional static typing for Python"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "mypy-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:566e72b0cd6598503e48ea610e0052d1b8168e60a46e0bfd34b3acf2d57f96a8"},
+ {file = "mypy-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ca637024ca67ab24a7fd6f65d280572c3794665eaf5edcc7e90a866544076878"},
+ {file = "mypy-1.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dde1d180cd84f0624c5dcaaa89c89775550a675aff96b5848de78fb11adabcd"},
+ {file = "mypy-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8c4d8e89aa7de683e2056a581ce63c46a0c41e31bd2b6d34144e2c80f5ea53dc"},
+ {file = "mypy-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:bfdca17c36ae01a21274a3c387a63aa1aafe72bff976522886869ef131b937f1"},
+ {file = "mypy-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7549fbf655e5825d787bbc9ecf6028731973f78088fbca3a1f4145c39ef09462"},
+ {file = "mypy-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:98324ec3ecf12296e6422939e54763faedbfcc502ea4a4c38502082711867258"},
+ {file = "mypy-1.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:141dedfdbfe8a04142881ff30ce6e6653c9685b354876b12e4fe6c78598b45e2"},
+ {file = "mypy-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8207b7105829eca6f3d774f64a904190bb2231de91b8b186d21ffd98005f14a7"},
+ {file = "mypy-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:16f0db5b641ba159eff72cff08edc3875f2b62b2fa2bc24f68c1e7a4e8232d01"},
+ {file = "mypy-1.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:470c969bb3f9a9efcedbadcd19a74ffb34a25f8e6b0e02dae7c0e71f8372f97b"},
+ {file = "mypy-1.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5952d2d18b79f7dc25e62e014fe5a23eb1a3d2bc66318df8988a01b1a037c5b"},
+ {file = "mypy-1.4.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:190b6bab0302cec4e9e6767d3eb66085aef2a1cc98fe04936d8a42ed2ba77bb7"},
+ {file = "mypy-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9d40652cc4fe33871ad3338581dca3297ff5f2213d0df345bcfbde5162abf0c9"},
+ {file = "mypy-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:01fd2e9f85622d981fd9063bfaef1aed6e336eaacca00892cd2d82801ab7c042"},
+ {file = "mypy-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2460a58faeea905aeb1b9b36f5065f2dc9a9c6e4c992a6499a2360c6c74ceca3"},
+ {file = "mypy-1.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2746d69a8196698146a3dbe29104f9eb6a2a4d8a27878d92169a6c0b74435b6"},
+ {file = "mypy-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ae704dcfaa180ff7c4cfbad23e74321a2b774f92ca77fd94ce1049175a21c97f"},
+ {file = "mypy-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:43d24f6437925ce50139a310a64b2ab048cb2d3694c84c71c3f2a1626d8101dc"},
+ {file = "mypy-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c482e1246726616088532b5e964e39765b6d1520791348e6c9dc3af25b233828"},
+ {file = "mypy-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:43b592511672017f5b1a483527fd2684347fdffc041c9ef53428c8dc530f79a3"},
+ {file = "mypy-1.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:34a9239d5b3502c17f07fd7c0b2ae6b7dd7d7f6af35fbb5072c6208e76295816"},
+ {file = "mypy-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5703097c4936bbb9e9bce41478c8d08edd2865e177dc4c52be759f81ee4dd26c"},
+ {file = "mypy-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e02d700ec8d9b1859790c0475df4e4092c7bf3272a4fd2c9f33d87fac4427b8f"},
+ {file = "mypy-1.4.1-py3-none-any.whl", hash = "sha256:45d32cec14e7b97af848bddd97d85ea4f0db4d5a149ed9676caa4eb2f7402bb4"},
+ {file = "mypy-1.4.1.tar.gz", hash = "sha256:9bbcd9ab8ea1f2e1c8031c21445b511442cc45c89951e49bbf852cbb70755b1b"},
+]
+
+[package.dependencies]
+mypy-extensions = ">=1.0.0"
+tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
+typing-extensions = ">=4.1.0"
+
+[package.extras]
+dmypy = ["psutil (>=4.0)"]
+install-types = ["pip"]
+python2 = ["typed-ast (>=1.4.0,<2)"]
+reports = ["lxml"]
+
+[[package]]
+name = "mypy-boto3-cloudwatch"
+version = "1.26.127"
+description = "Type annotations for boto3.CloudWatch 1.26.127 service generated with mypy-boto3-builder 7.14.5"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "mypy-boto3-cloudwatch-1.26.127.tar.gz", hash = "sha256:08281b75414293f112135eaaa9937ab2621e1db0762285a1face66ab937b4e0f"},
+ {file = "mypy_boto3_cloudwatch-1.26.127-py3-none-any.whl", hash = "sha256:e2da3e956b1c67a3bc4374ced3331fff97172f98d63e56efea805dc1e5fa28e9"},
+]
+
+[[package]]
+name = "mypy-boto3-dynamodb"
+version = "1.26.164"
+description = "Type annotations for boto3.DynamoDB 1.26.164 service generated with mypy-boto3-builder 7.14.5"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "mypy-boto3-dynamodb-1.26.164.tar.gz", hash = "sha256:5a832531ac2c81b01dea20ef79f7dd5a2014c3736566a498585f5f46d642adc4"},
+ {file = "mypy_boto3_dynamodb-1.26.164-py3-none-any.whl", hash = "sha256:a527270b304f1a517093fff3709c7831fc5616a91bb1c9b6164fa71e37481d84"},
+]
+
+[[package]]
+name = "mypy-boto3-ec2"
+version = "1.26.157"
+description = "Type annotations for boto3.EC2 1.26.157 service generated with mypy-boto3-builder 7.14.5"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "mypy-boto3-ec2-1.26.157.tar.gz", hash = "sha256:43c1051141d407d138a2a0dd02780790472f58c390e9fe7b61f71433d6982102"},
+ {file = "mypy_boto3_ec2-1.26.157-py3-none-any.whl", hash = "sha256:02b386673169b0a8174b7b3496c2afd54ebdaba23a70c51f3f1b8c62ac9259d4"},
+]
+
+[[package]]
+name = "mypy-boto3-lambda"
+version = "1.26.163"
+description = "Type annotations for boto3.Lambda 1.26.163 service generated with mypy-boto3-builder 7.14.5"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "mypy-boto3-lambda-1.26.163.tar.gz", hash = "sha256:fd36cf8a3f5e733f6e80c755af19538ce0a50c3eafb1be7cf7de0c29c40788a0"},
+ {file = "mypy_boto3_lambda-1.26.163-py3-none-any.whl", hash = "sha256:f6ca7fd11c8e9c81218fdbeae163c343c6dc3b7df88a70c30c0c7b30c90163d9"},
+]
+
+[[package]]
+name = "mypy-boto3-logs"
+version = "1.26.149"
+description = "Type annotations for boto3.CloudWatchLogs 1.26.149 service generated with mypy-boto3-builder 7.14.5"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "mypy-boto3-logs-1.26.149.tar.gz", hash = "sha256:4a592d7d8180d45197197af4dc959f61b5c4d989a0ba615ecde6e21661c4013f"},
+ {file = "mypy_boto3_logs-1.26.149-py3-none-any.whl", hash = "sha256:6d913c9be74c9eff71910b5af18f8beeeae524dae273fea7b47ead0ee1a09134"},
+]
+
+[[package]]
+name = "mypy-boto3-rds"
+version = "1.26.163"
+description = "Type annotations for boto3.RDS 1.26.163 service generated with mypy-boto3-builder 7.14.5"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "mypy-boto3-rds-1.26.163.tar.gz", hash = "sha256:b37a1d02e42e5fc5bead20b7f0541d667a2161dd3af705a976ad2362cb12f5ba"},
+ {file = "mypy_boto3_rds-1.26.163-py3-none-any.whl", hash = "sha256:bf61bc6262d608600ccdabce9f3104ddac766f1e3a466fa48533d633027526f4"},
+]
+
+[[package]]
+name = "mypy-boto3-resourcegroupstaggingapi"
+version = "1.26.0.post1"
+description = "Type annotations for boto3.ResourceGroupsTaggingAPI 1.26.0 service generated with mypy-boto3-builder 7.11.10"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "mypy-boto3-resourcegroupstaggingapi-1.26.0.post1.tar.gz", hash = "sha256:3fda6613449f14ccc63f06a21d40a05b887c5e3f24d612731b0075dbf57e8148"},
+ {file = "mypy_boto3_resourcegroupstaggingapi-1.26.0.post1-py3-none-any.whl", hash = "sha256:8f7117b6820b4ed128bf4de0854dc5a8e015661381aac6fbaa5dc8507ab351b6"},
+]
+
+[package.dependencies]
+typing-extensions = ">=4.1.0"
+
+[[package]]
+name = "mypy-boto3-sns"
+version = "1.26.69"
+description = "Type annotations for boto3.SNS 1.26.69 service generated with mypy-boto3-builder 7.12.3"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "mypy-boto3-sns-1.26.69.tar.gz", hash = "sha256:3cf0b746ee2c66fb7cb318ff19b34c148cb308f9a47b7d7668980de4cfe9f8a9"},
+ {file = "mypy_boto3_sns-1.26.69-py3-none-any.whl", hash = "sha256:d4cf04336cf0394b9e0143f35a553c7279b30691f16b90c11ef9cb836dd241d5"},
+]
+
+[package.dependencies]
+typing-extensions = ">=4.1.0"
+
+[[package]]
+name = "mypy-boto3-ssm"
+version = "1.26.162"
+description = "Type annotations for boto3.SSM 1.26.162 service generated with mypy-boto3-builder 7.14.5"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "mypy-boto3-ssm-1.26.162.tar.gz", hash = "sha256:a5d9d7e4c7dbf4788dddcc02410afa349d7356a24fbffe5b7a36cd0c04211f06"},
+ {file = "mypy_boto3_ssm-1.26.162-py3-none-any.whl", hash = "sha256:42c52e55a94b5d5ce14d628b4bc168b2b4230e130050172bf54747edb7b8da14"},
+]
+
+[[package]]
+name = "mypy-boto3-sts"
+version = "1.26.136"
+description = "Type annotations for boto3.STS 1.26.136 service generated with mypy-boto3-builder 7.14.5"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "mypy-boto3-sts-1.26.136.tar.gz", hash = "sha256:d326916d6f21252f7a7c0086a7da3f5e4a6eb6c7470e7588a4c9b825cb0a01fe"},
+ {file = "mypy_boto3_sts-1.26.136-py3-none-any.whl", hash = "sha256:447766738b971a0d74c291062fe022f7d75e2ccda7cb1bd0cad5a5612e51c779"},
+]
+
[[package]]
name = "mypy-extensions"
version = "1.0.0"
@@ -700,50 +1378,65 @@ files = [
{file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"},
]
-[[package]]
-name = "pbr"
-version = "5.11.1"
-description = "Python Build Reasonableness"
-category = "dev"
-optional = false
-python-versions = ">=2.6"
-files = [
- {file = "pbr-5.11.1-py2.py3-none-any.whl", hash = "sha256:567f09558bae2b3ab53cb3c1e2e33e726ff3338e7bae3db5dc954b3a44eef12b"},
- {file = "pbr-5.11.1.tar.gz", hash = "sha256:aefc51675b0b533d56bb5fd1c8c6c0522fe31896679882e1c4c63d5e4a0fccb3"},
-]
-
[[package]]
name = "platformdirs"
-version = "3.2.0"
+version = "3.8.1"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "platformdirs-3.2.0-py3-none-any.whl", hash = "sha256:ebe11c0d7a805086e99506aa331612429a72ca7cd52a1f0d277dc4adc20cb10e"},
- {file = "platformdirs-3.2.0.tar.gz", hash = "sha256:d5b638ca397f25f979350ff789db335903d7ea010ab28903f57b27e1b16c2b08"},
+ {file = "platformdirs-3.8.1-py3-none-any.whl", hash = "sha256:cec7b889196b9144d088e4c57d9ceef7374f6c39694ad1577a0aab50d27ea28c"},
+ {file = "platformdirs-3.8.1.tar.gz", hash = "sha256:f87ca4fcff7d2b0f81c6a748a77973d7af0f4d526f98f308477c3c436c74d528"},
]
[package.extras]
-docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"]
-test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
+docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
+test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)"]
[[package]]
name = "pluggy"
-version = "1.0.0"
+version = "1.2.0"
description = "plugin and hook calling mechanisms for python"
category = "dev"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
files = [
- {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
- {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
+ {file = "pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849"},
+ {file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"},
]
[package.extras]
dev = ["pre-commit", "tox"]
testing = ["pytest", "pytest-benchmark"]
+[[package]]
+name = "py-partiql-parser"
+version = "0.3.3"
+description = "Pure Python PartiQL Parser"
+category = "dev"
+optional = false
+python-versions = "*"
+files = [
+ {file = "py-partiql-parser-0.3.3.tar.gz", hash = "sha256:351672721dfaaa00bbd82c4a3340d5d2defb589d2dd5baaecf6e493910f1c033"},
+ {file = "py_partiql_parser-0.3.3-py3-none-any.whl", hash = "sha256:cd4a53af362bb589968b17b321d1ac46d06d21d333247e0e6f79b11db2d0306f"},
+]
+
+[package.extras]
+dev = ["black (==22.6.0)", "flake8", "mypy (==0.971)", "pytest", "sure (==2.0.0)"]
+
+[[package]]
+name = "pycodestyle"
+version = "2.10.0"
+description = "Python style guide checker"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "pycodestyle-2.10.0-py2.py3-none-any.whl", hash = "sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610"},
+ {file = "pycodestyle-2.10.0.tar.gz", hash = "sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053"},
+]
+
[[package]]
name = "pycparser"
version = "2.21"
@@ -756,36 +1449,48 @@ files = [
{file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
]
+[[package]]
+name = "pyflakes"
+version = "3.0.1"
+description = "passive checker of Python programs"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "pyflakes-3.0.1-py2.py3-none-any.whl", hash = "sha256:ec55bf7fe21fff7f1ad2f7da62363d749e2a470500eab1b555334b67aa1ef8cf"},
+ {file = "pyflakes-3.0.1.tar.gz", hash = "sha256:ec8b276a6b60bd80defed25add7e439881c19e64850afd9b346283d4165fd0fd"},
+]
+
[[package]]
name = "pyproject-api"
-version = "1.5.1"
+version = "1.5.3"
description = "API to interact with the python pyproject.toml based projects"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "pyproject_api-1.5.1-py3-none-any.whl", hash = "sha256:4698a3777c2e0f6b624f8a4599131e2a25376d90fe8d146d7ac74c67c6f97c43"},
- {file = "pyproject_api-1.5.1.tar.gz", hash = "sha256:435f46547a9ff22cf4208ee274fca3e2869aeb062a4834adfc99a4dd64af3cf9"},
+ {file = "pyproject_api-1.5.3-py3-none-any.whl", hash = "sha256:14cf09828670c7b08842249c1f28c8ee6581b872e893f81b62d5465bec41502f"},
+ {file = "pyproject_api-1.5.3.tar.gz", hash = "sha256:ffb5b2d7cad43f5b2688ab490de7c4d3f6f15e0b819cb588c4b771567c9729eb"},
]
[package.dependencies]
-packaging = ">=23"
+packaging = ">=23.1"
tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""}
[package.extras]
-docs = ["furo (>=2022.12.7)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"]
-testing = ["covdefaults (>=2.2.2)", "importlib-metadata (>=6)", "pytest (>=7.2.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "virtualenv (>=20.17.1)", "wheel (>=0.38.4)"]
+docs = ["furo (>=2023.5.20)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
+testing = ["covdefaults (>=2.3)", "importlib-metadata (>=6.6)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)", "setuptools (>=67.8)", "wheel (>=0.40)"]
[[package]]
name = "pytest"
-version = "7.3.0"
+version = "7.4.0"
description = "pytest: simple powerful testing with Python"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "pytest-7.3.0-py3-none-any.whl", hash = "sha256:933051fa1bfbd38a21e73c3960cebdad4cf59483ddba7696c48509727e17f201"},
- {file = "pytest-7.3.0.tar.gz", hash = "sha256:58ecc27ebf0ea643ebfdf7fb1249335da761a00c9f955bcd922349bcb68ee57d"},
+ {file = "pytest-7.4.0-py3-none-any.whl", hash = "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32"},
+ {file = "pytest-7.4.0.tar.gz", hash = "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a"},
]
[package.dependencies]
@@ -797,18 +1502,18 @@ pluggy = ">=0.12,<2.0"
tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
[package.extras]
-testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
+testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
[[package]]
name = "pytest-cov"
-version = "4.0.0"
+version = "4.1.0"
description = "Pytest plugin for measuring coverage."
category = "dev"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.7"
files = [
- {file = "pytest-cov-4.0.0.tar.gz", hash = "sha256:996b79efde6433cdbd0088872dbc5fb3ed7fe1578b68cdbba634f14bb8dd0470"},
- {file = "pytest_cov-4.0.0-py3-none-any.whl", hash = "sha256:2feb1b751d66a8bd934e5edfa2e961d11309dc37b73b0eabe73b5945fee20f6b"},
+ {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"},
+ {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"},
]
[package.dependencies]
@@ -820,37 +1525,58 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale
[[package]]
name = "pytest-mock"
-version = "1.13.0"
-description = "Thin-wrapper around the mock package for easier use with py.test"
+version = "3.11.1"
+description = "Thin-wrapper around the mock package for easier use with pytest"
category = "dev"
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+python-versions = ">=3.7"
files = [
- {file = "pytest-mock-1.13.0.tar.gz", hash = "sha256:e24a911ec96773022ebcc7030059b57cd3480b56d4f5d19b7c370ec635e6aed5"},
- {file = "pytest_mock-1.13.0-py2.py3-none-any.whl", hash = "sha256:67e414b3caef7bff6fc6bd83b22b5bc39147e4493f483c2679bc9d4dc485a94d"},
+ {file = "pytest-mock-3.11.1.tar.gz", hash = "sha256:7f6b125602ac6d743e523ae0bfa71e1a697a2f5534064528c6ff84c2f7c2fc7f"},
+ {file = "pytest_mock-3.11.1-py3-none-any.whl", hash = "sha256:21c279fff83d70763b05f8874cc9cfb3fcacd6d354247a976f9529d19f9acf39"},
]
[package.dependencies]
-pytest = ">=2.7"
+pytest = ">=5.0"
[package.extras]
-dev = ["pre-commit", "tox"]
+dev = ["pre-commit", "pytest-asyncio", "tox"]
[[package]]
name = "pytest-runner"
-version = "2.12.2"
+version = "6.0.0"
description = "Invoke py.test as distutils command with dependency resolution"
category = "dev"
optional = false
-python-versions = ">=2.6"
+python-versions = ">=3.7"
files = [
- {file = "pytest-runner-2.12.2.tar.gz", hash = "sha256:868fd7ad6b0c860b5c5cefb8c51ef206794fb622e789e53cd9135e0793943b86"},
- {file = "pytest_runner-2.12.2-py2.py3-none-any.whl", hash = "sha256:1413962beb397705ddfae1fcdb8cd72e05bf6b4974b23f1d78dc14bc13af9b43"},
+ {file = "pytest-runner-6.0.0.tar.gz", hash = "sha256:b4d85362ed29b4c348678de797df438f0f0509497ddb8c647096c02a6d87b685"},
+ {file = "pytest_runner-6.0.0-py3-none-any.whl", hash = "sha256:4c059cf11cf4306e369c0f8f703d1eaf8f32fad370f41deb5f007044656aca6b"},
]
[package.extras]
-docs = ["jaraco.packaging (>=3.2)", "rst.linker (>=1.9)", "sphinx"]
-testing = ["collective.checkdocs", "importlib", "pytest (>=2.8)", "pytest-sugar", "pytest-virtualenv"]
+docs = ["jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx"]
+testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.0.1)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-virtualenv", "types-setuptools"]
+
+[[package]]
+name = "pytest-xdist"
+version = "3.3.1"
+description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pytest-xdist-3.3.1.tar.gz", hash = "sha256:d5ee0520eb1b7bcca50a60a518ab7a7707992812c578198f8b44fdfac78e8c93"},
+ {file = "pytest_xdist-3.3.1-py3-none-any.whl", hash = "sha256:ff9daa7793569e6a68544850fd3927cd257cc03a7ef76c95e86915355e82b5f2"},
+]
+
+[package.dependencies]
+execnet = ">=1.1"
+pytest = ">=6.2.0"
+
+[package.extras]
+psutil = ["psutil (>=3.0)"]
+setproctitle = ["setproctitle"]
+testing = ["filelock"]
[[package]]
name = "python-dateutil"
@@ -868,15 +1594,27 @@ files = [
six = ">=1.5"
[[package]]
-name = "pytz"
-version = "2023.3"
-description = "World timezone definitions, modern and historical"
-category = "main"
+name = "pywin32"
+version = "306"
+description = "Python for Window Extensions"
+category = "dev"
optional = false
python-versions = "*"
files = [
- {file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"},
- {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"},
+ {file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"},
+ {file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"},
+ {file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"},
+ {file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"},
+ {file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"},
+ {file = "pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b"},
+ {file = "pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e"},
+ {file = "pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040"},
+ {file = "pywin32-306-cp37-cp37m-win32.whl", hash = "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65"},
+ {file = "pywin32-306-cp37-cp37m-win_amd64.whl", hash = "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36"},
+ {file = "pywin32-306-cp38-cp38-win32.whl", hash = "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a"},
+ {file = "pywin32-306-cp38-cp38-win_amd64.whl", hash = "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0"},
+ {file = "pywin32-306-cp39-cp39-win32.whl", hash = "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802"},
+ {file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"},
]
[[package]]
@@ -931,21 +1669,21 @@ files = [
[[package]]
name = "requests"
-version = "2.28.2"
+version = "2.31.0"
description = "Python HTTP for Humans."
category = "main"
optional = false
-python-versions = ">=3.7, <4"
+python-versions = ">=3.7"
files = [
- {file = "requests-2.28.2-py3-none-any.whl", hash = "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"},
- {file = "requests-2.28.2.tar.gz", hash = "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"},
+ {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"},
+ {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"},
]
[package.dependencies]
certifi = ">=2017.4.17"
charset-normalizer = ">=2,<4"
idna = ">=2.5,<4"
-urllib3 = ">=1.21.1,<1.27"
+urllib3 = ">=1.21.1,<3"
[package.extras]
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
@@ -974,14 +1712,14 @@ tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asy
[[package]]
name = "s3transfer"
-version = "0.6.0"
+version = "0.6.1"
description = "An Amazon S3 Transfer Manager"
category = "dev"
optional = false
python-versions = ">= 3.7"
files = [
- {file = "s3transfer-0.6.0-py3-none-any.whl", hash = "sha256:06176b74f3a15f61f1b4f25a1fc29a4429040b7647133a463da8fa5bd28d5ecd"},
- {file = "s3transfer-0.6.0.tar.gz", hash = "sha256:2ed07d3866f523cc561bf4a00fc5535827981b117dd7876f036b0c1aca42c947"},
+ {file = "s3transfer-0.6.1-py3-none-any.whl", hash = "sha256:3c0da2d074bf35d6870ef157158641178a4204a6e689e82546083e31e0311346"},
+ {file = "s3transfer-0.6.1.tar.gz", hash = "sha256:640bb492711f4c0c0905e1f62b6aaeb771881935ad27884852411f8e9cacbca9"},
]
[package.dependencies]
@@ -990,23 +1728,6 @@ botocore = ">=1.12.36,<2.0a.0"
[package.extras]
crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"]
-[[package]]
-name = "setuptools"
-version = "67.0.0"
-description = "Easily download, build, install, upgrade, and uninstall Python packages"
-category = "dev"
-optional = false
-python-versions = ">=3.7"
-files = [
- {file = "setuptools-67.0.0-py3-none-any.whl", hash = "sha256:9d790961ba6219e9ff7d9557622d2fe136816a264dd01d5997cfc057d804853d"},
- {file = "setuptools-67.0.0.tar.gz", hash = "sha256:883131c5b6efa70b9101c7ef30b2b7b780a4283d5fc1616383cdf22c83cbefe6"},
-]
-
-[package.extras]
-docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
-testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
-testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
-
[[package]]
name = "six"
version = "1.16.0"
@@ -1019,6 +1740,25 @@ files = [
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
]
+[[package]]
+name = "sshpubkeys"
+version = "3.3.1"
+description = "SSH public key parser"
+category = "dev"
+optional = false
+python-versions = ">=3"
+files = [
+ {file = "sshpubkeys-3.3.1-py2.py3-none-any.whl", hash = "sha256:946f76b8fe86704b0e7c56a00d80294e39bc2305999844f079a217885060b1ac"},
+ {file = "sshpubkeys-3.3.1.tar.gz", hash = "sha256:3020ed4f8c846849299370fbe98ff4157b0ccc1accec105e07cfa9ae4bb55064"},
+]
+
+[package.dependencies]
+cryptography = ">=2.1.4"
+ecdsa = ">=0.13"
+
+[package.extras]
+dev = ["twine", "wheel", "yapf"]
+
[[package]]
name = "tomli"
version = "2.0.1"
@@ -1033,66 +1773,168 @@ files = [
[[package]]
name = "tox"
-version = "4.4.11"
+version = "4.6.4"
description = "tox is a generic virtualenv management and test command line tool"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "tox-4.4.11-py3-none-any.whl", hash = "sha256:6fa4dbd933d0e335b5392c81e9cd467630119b3669705dbad47814a93b6c9586"},
- {file = "tox-4.4.11.tar.gz", hash = "sha256:cd88e41aef9c71f0ba02b6d7939f102760b192b63458fbe04dbbaed82f7bf5f5"},
+ {file = "tox-4.6.4-py3-none-any.whl", hash = "sha256:1b8f8ae08d6a5475cad9d508236c51ea060620126fd7c3c513d0f5c7f29cc776"},
+ {file = "tox-4.6.4.tar.gz", hash = "sha256:5e2ad8845764706170d3dcaac171704513cc8a725655219acb62fe4380bdadda"},
]
[package.dependencies]
-cachetools = ">=5.3"
+cachetools = ">=5.3.1"
chardet = ">=5.1"
colorama = ">=0.4.6"
-filelock = ">=3.10.7"
-packaging = ">=23"
-platformdirs = ">=3.2"
-pluggy = ">=1"
-pyproject-api = ">=1.5.1"
+filelock = ">=3.12.2"
+packaging = ">=23.1"
+platformdirs = ">=3.8"
+pluggy = ">=1.2"
+pyproject-api = ">=1.5.2"
tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""}
-virtualenv = ">=20.21"
+virtualenv = ">=20.23.1"
[package.extras]
-docs = ["furo (>=2023.3.27)", "sphinx (>=6.1.3)", "sphinx-argparse-cli (>=1.11)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)", "sphinx-copybutton (>=0.5.1)", "sphinx-inline-tabs (>=2022.1.2b11)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=22.12)"]
-testing = ["build[virtualenv] (>=0.10)", "covdefaults (>=2.3)", "devpi-process (>=0.3)", "diff-cover (>=7.5)", "distlib (>=0.3.6)", "flaky (>=3.7)", "hatch-vcs (>=0.3)", "hatchling (>=1.13)", "psutil (>=5.9.4)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)", "pytest-xdist (>=3.2.1)", "re-assert (>=1.1)", "time-machine (>=2.9)", "wheel (>=0.40)"]
+docs = ["furo (>=2023.5.20)", "sphinx (>=7.0.1)", "sphinx-argparse-cli (>=1.11.1)", "sphinx-autodoc-typehints (>=1.23.3,!=1.23.4)", "sphinx-copybutton (>=0.5.2)", "sphinx-inline-tabs (>=2023.4.21)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
+testing = ["build[virtualenv] (>=0.10)", "covdefaults (>=2.3)", "detect-test-pollution (>=1.1.1)", "devpi-process (>=0.3.1)", "diff-cover (>=7.6)", "distlib (>=0.3.6)", "flaky (>=3.7)", "hatch-vcs (>=0.3)", "hatchling (>=1.17.1)", "psutil (>=5.9.5)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)", "pytest-xdist (>=3.3.1)", "re-assert (>=1.1)", "time-machine (>=2.10)", "wheel (>=0.40)"]
+
+[[package]]
+name = "types-awscrt"
+version = "0.16.23"
+description = "Type annotations and code completion for awscrt"
+category = "dev"
+optional = false
+python-versions = ">=3.7,<4.0"
+files = [
+ {file = "types_awscrt-0.16.23-py3-none-any.whl", hash = "sha256:7edec4283fec9f92574444ce45fc0be65c846056634628aee22c118712da71c4"},
+ {file = "types_awscrt-0.16.23.tar.gz", hash = "sha256:5a846b77a6d35b63ccf9d33abf386c4dfc6275f9c062bc0e234c14ea8c6013a9"},
+]
+
+[[package]]
+name = "types-freezegun"
+version = "1.1.10"
+description = "Typing stubs for freezegun"
+category = "dev"
+optional = false
+python-versions = "*"
+files = [
+ {file = "types-freezegun-1.1.10.tar.gz", hash = "sha256:cb3a2d2eee950eacbaac0673ab50499823365ceb8c655babb1544a41446409ec"},
+ {file = "types_freezegun-1.1.10-py3-none-any.whl", hash = "sha256:fadebe72213e0674036153366205038e1f95c8ca96deb4ef9b71ddc15413543e"},
+]
+
+[[package]]
+name = "types-jmespath"
+version = "1.0.2.6"
+description = "Typing stubs for jmespath"
+category = "dev"
+optional = false
+python-versions = "*"
+files = [
+ {file = "types-jmespath-1.0.2.6.tar.gz", hash = "sha256:4992c1f1a97ee374e3825e057b262930b36f02be71a9c3e3394d5aab5e63dc29"},
+ {file = "types_jmespath-1.0.2.6-py3-none-any.whl", hash = "sha256:867fb88e4a04f633080dc74222a0b0e9684a2e6cc7c5d3a9e57e2b8ccf40bff7"},
+]
+
+[[package]]
+name = "types-python-dateutil"
+version = "2.8.19.13"
+description = "Typing stubs for python-dateutil"
+category = "dev"
+optional = false
+python-versions = "*"
+files = [
+ {file = "types-python-dateutil-2.8.19.13.tar.gz", hash = "sha256:09a0275f95ee31ce68196710ed2c3d1b9dc42e0b61cc43acc369a42cb939134f"},
+ {file = "types_python_dateutil-2.8.19.13-py3-none-any.whl", hash = "sha256:0b0e7c68e7043b0354b26a1e0225cb1baea7abb1b324d02b50e2d08f1221043f"},
+]
[[package]]
name = "types-pyyaml"
-version = "6.0.12.9"
+version = "6.0.12.10"
description = "Typing stubs for PyYAML"
category = "dev"
optional = false
python-versions = "*"
files = [
- {file = "types-PyYAML-6.0.12.9.tar.gz", hash = "sha256:c51b1bd6d99ddf0aa2884a7a328810ebf70a4262c292195d3f4f9a0005f9eeb6"},
- {file = "types_PyYAML-6.0.12.9-py3-none-any.whl", hash = "sha256:5aed5aa66bd2d2e158f75dda22b059570ede988559f030cf294871d3b647e3e8"},
+ {file = "types-PyYAML-6.0.12.10.tar.gz", hash = "sha256:ebab3d0700b946553724ae6ca636ea932c1b0868701d4af121630e78d695fc97"},
+ {file = "types_PyYAML-6.0.12.10-py3-none-any.whl", hash = "sha256:662fa444963eff9b68120d70cda1af5a5f2aa57900003c2006d7626450eaae5f"},
+]
+
+[[package]]
+name = "types-requests"
+version = "2.31.0.1"
+description = "Typing stubs for requests"
+category = "dev"
+optional = false
+python-versions = "*"
+files = [
+ {file = "types-requests-2.31.0.1.tar.gz", hash = "sha256:3de667cffa123ce698591de0ad7db034a5317457a596eb0b4944e5a9d9e8d1ac"},
+ {file = "types_requests-2.31.0.1-py3-none-any.whl", hash = "sha256:afb06ef8f25ba83d59a1d424bd7a5a939082f94b94e90ab5e6116bd2559deaa3"},
+]
+
+[package.dependencies]
+types-urllib3 = "*"
+
+[[package]]
+name = "types-s3transfer"
+version = "0.6.1"
+description = "Type annotations and code completion for s3transfer"
+category = "dev"
+optional = false
+python-versions = ">=3.7,<4.0"
+files = [
+ {file = "types_s3transfer-0.6.1-py3-none-any.whl", hash = "sha256:6d1ac1dedac750d570428362acdf60fdd4f277b0788855c3894d3226756b2bfb"},
+ {file = "types_s3transfer-0.6.1.tar.gz", hash = "sha256:75ac1d7143d58c1e6af467cfd4a96c67ee058a3adf7c249d9309999e1f5f41e4"},
+]
+
+[package.dependencies]
+types-awscrt = "*"
+
+[[package]]
+name = "types-urllib3"
+version = "1.26.25.13"
+description = "Typing stubs for urllib3"
+category = "dev"
+optional = false
+python-versions = "*"
+files = [
+ {file = "types-urllib3-1.26.25.13.tar.gz", hash = "sha256:3300538c9dc11dad32eae4827ac313f5d986b8b21494801f1bf97a1ac6c03ae5"},
+ {file = "types_urllib3-1.26.25.13-py3-none-any.whl", hash = "sha256:5dbd1d2bef14efee43f5318b5d36d805a489f6600252bb53626d4bfafd95e27c"},
]
[[package]]
name = "typing-extensions"
-version = "4.5.0"
+version = "4.7.1"
description = "Backported and Experimental Type Hints for Python 3.7+"
-category = "dev"
+category = "main"
optional = false
python-versions = ">=3.7"
files = [
- {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"},
- {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"},
+ {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"},
+ {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"},
+]
+
+[[package]]
+name = "tzdata"
+version = "2023.3"
+description = "Provider of IANA time zone data"
+category = "dev"
+optional = false
+python-versions = ">=2"
+files = [
+ {file = "tzdata-2023.3-py2.py3-none-any.whl", hash = "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"},
+ {file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"},
]
[[package]]
name = "urllib3"
-version = "1.26.15"
+version = "1.26.16"
description = "HTTP library with thread-safe connection pooling, file post, and more."
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
files = [
- {file = "urllib3-1.26.15-py2.py3-none-any.whl", hash = "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"},
- {file = "urllib3-1.26.15.tar.gz", hash = "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305"},
+ {file = "urllib3-1.26.16-py2.py3-none-any.whl", hash = "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f"},
+ {file = "urllib3-1.26.16.tar.gz", hash = "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14"},
]
[package.extras]
@@ -1101,54 +1943,60 @@ secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "p
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
[[package]]
-name = "uuid"
-version = "1.30"
-description = "UUID object and generation functions (Python 2.3 or higher)"
+name = "virtualenv"
+version = "20.23.1"
+description = "Virtual Python Environment builder"
category = "dev"
optional = false
-python-versions = "*"
+python-versions = ">=3.7"
files = [
- {file = "uuid-1.30.tar.gz", hash = "sha256:1f87cc004ac5120466f36c5beae48b4c48cc411968eed0eaecd3da82aa96193f"},
+ {file = "virtualenv-20.23.1-py3-none-any.whl", hash = "sha256:34da10f14fea9be20e0fd7f04aba9732f84e593dac291b757ce42e3368a39419"},
+ {file = "virtualenv-20.23.1.tar.gz", hash = "sha256:8ff19a38c1021c742148edc4f81cb43d7f8c6816d2ede2ab72af5b84c749ade1"},
]
+[package.dependencies]
+distlib = ">=0.3.6,<1"
+filelock = ">=3.12,<4"
+platformdirs = ">=3.5.1,<4"
+
+[package.extras]
+docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
+test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.3.1)", "pytest-env (>=0.8.1)", "pytest-freezer (>=0.4.6)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=67.8)", "time-machine (>=2.9)"]
+
[[package]]
-name = "virtualenv"
-version = "20.21.0"
-description = "Virtual Python Environment builder"
+name = "websocket-client"
+version = "1.6.1"
+description = "WebSocket client for Python with low level API options"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "virtualenv-20.21.0-py3-none-any.whl", hash = "sha256:31712f8f2a17bd06234fa97fdf19609e789dd4e3e4bf108c3da71d710651adbc"},
- {file = "virtualenv-20.21.0.tar.gz", hash = "sha256:f50e3e60f990a0757c9b68333c9fdaa72d7188caa417f96af9e52407831a3b68"},
+ {file = "websocket-client-1.6.1.tar.gz", hash = "sha256:c951af98631d24f8df89ab1019fc365f2227c0892f12fd150e935607c79dd0dd"},
+ {file = "websocket_client-1.6.1-py3-none-any.whl", hash = "sha256:f1f9f2ad5291f0225a49efad77abf9e700b6fef553900623060dad6e26503b9d"},
]
-[package.dependencies]
-distlib = ">=0.3.6,<1"
-filelock = ">=3.4.1,<4"
-platformdirs = ">=2.4,<4"
-
[package.extras]
-docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=22.12)"]
-test = ["covdefaults (>=2.2.2)", "coverage (>=7.1)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23)", "pytest (>=7.2.1)", "pytest-env (>=0.8.1)", "pytest-freezegun (>=0.4.2)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)"]
+docs = ["Sphinx (>=3.4)", "sphinx-rtd-theme (>=0.5)"]
+optional = ["python-socks", "wsaccel"]
+test = ["websockets"]
[[package]]
name = "werkzeug"
-version = "2.2.3"
+version = "2.3.6"
description = "The comprehensive WSGI web application library."
category = "dev"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "Werkzeug-2.2.3-py3-none-any.whl", hash = "sha256:56433961bc1f12533306c624f3be5e744389ac61d722175d543e1751285da612"},
- {file = "Werkzeug-2.2.3.tar.gz", hash = "sha256:2e1ccc9417d4da358b9de6f174e3ac094391ea1d4fbef2d667865d819dfd0afe"},
+ {file = "Werkzeug-2.3.6-py3-none-any.whl", hash = "sha256:935539fa1413afbb9195b24880778422ed620c0fc09670945185cce4d91a8890"},
+ {file = "Werkzeug-2.3.6.tar.gz", hash = "sha256:98c774df2f91b05550078891dee5f0eb0cb797a522c757a2452b9cee5b202330"},
]
[package.dependencies]
MarkupSafe = ">=2.1.1"
[package.extras]
-watchdog = ["watchdog"]
+watchdog = ["watchdog (>=2.3)"]
[[package]]
name = "xmltodict"
@@ -1164,5 +2012,5 @@ files = [
[metadata]
lock-version = "2.0"
-python-versions = "^3.9"
-content-hash = "f0d2d9954d03f6c09f422417673a8e84bd8aa133fc8de84395c3910e58ee1f57"
+python-versions = "^3.10"
+content-hash = "c32959317c39d1e3d7d9ff1acfcde086510be88f2a8ce7744bfaa034e4809771"
diff --git a/source/app/pyproject.toml b/source/app/pyproject.toml
index b4073871..098a2630 100644
--- a/source/app/pyproject.toml
+++ b/source/app/pyproject.toml
@@ -5,29 +5,41 @@ requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.poetry]
-name = "InstanceScheduler-Lambda"
-version = "1.5.0"
-description = "AWS Instance Scheduler"
-authors = ["AWS"]
-packages = [{ include="instance_scheduler" }]
+name = "instance_scheduler"
+version = "1.5.1"
+description = "Instance Scheduler on AWS"
+license = "Apache-2.0"
+authors = ["Amazon Web Services"]
+homepage = "https://aws.amazon.com/solutions/implementations/instance-scheduler-on-aws/"
+repository = "https://github.com/aws-solutions/instance-scheduler-on-aws"
+documentation = "https://docs.aws.amazon.com/solutions/latest/instance-scheduler-on-aws/solution-overview.html"
[tool.poetry.dependencies]
-python = "^3.9"
-pytz = "^2023.3"
-requests = "^2.28.2"
-chardet = "^5.1.0"
+python = "^3.10"
+requests = "^2.31.0"
+typing-extensions = "^4.7.1"
[tool.poetry.group.dev.dependencies]
-tox = "^4.4.11"
-botocore = "^1.9.99"
-boto3 = "^1.9.99"
-mock = "^2.0.0"
-pytest = "^7.2.0"
-pytest-cov = "^4.0.0"
-pytest-mock = "^1.10.4"
-pytest-runner = "^2.11.1"
-uuid = "^1.30"
-moto = "^4.0.0"
-setuptools = "67.0.0"
-freezegun = "^0.3.15"
-black = "^23.1.0"
+aws-lambda-powertools = "^2.19.0"
+black = "^23.7.0"
+boto3 = "1.26.90"
+boto3-stubs-lite = {extras = ["cloudwatch", "dynamodb", "ec2", "lambda", "logs", "rds", "resourcegroupstaggingapi", "sns", "ssm", "sts"], version = "1.26.90"}
+botocore = "1.29.90"
+flake8 = "^6.0.0"
+freezegun = "^1.2.2"
+isort = "^5.12.0"
+jmespath = "1.0.1"
+pytest = "^7.4.0"
+pytest-cov = "^4.1.0"
+pytest-mock = "^3.11.1"
+pytest-runner = "^6.0.0"
+python-dateutil = "2.8.2"
+moto = {extras = ["dynamodb", "ec2", "logs", "rds", "resourcegroupstaggingapi", "ssm"], version = "^4.1.12"}
+mypy = "^1.4.1"
+tox = "^4.6.4"
+types-freezegun = "^1.1.10"
+types-jmespath = "^1.0.2.6"
+types-python-dateutil = "^2.8.19.13"
+types-requests = "^2.31.0.1"
+tzdata = "^2023.3"
+pytest-xdist = "^3.3.1"
diff --git a/source/app/tests/__init__.py b/source/app/tests/__init__.py
new file mode 100644
index 00000000..f35cbf57
--- /dev/null
+++ b/source/app/tests/__init__.py
@@ -0,0 +1,5 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from typing import Final as _Final
+
+ami: _Final = "ami-0889ff9188674a22a"
diff --git a/source/app/instance_scheduler/requesthandlers/__init__.py b/source/app/tests/boto_retry/__init__.py
similarity index 100%
rename from source/app/instance_scheduler/requesthandlers/__init__.py
rename to source/app/tests/boto_retry/__init__.py
diff --git a/source/app/tests/boto_retry/test_boto_retry_init.py b/source/app/tests/boto_retry/test_boto_retry_init.py
new file mode 100644
index 00000000..a62a1701
--- /dev/null
+++ b/source/app/tests/boto_retry/test_boto_retry_init.py
@@ -0,0 +1,18 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from typing import TYPE_CHECKING
+
+from moto import mock_ec2
+
+from instance_scheduler.boto_retry import get_client_with_standard_retry
+
+if TYPE_CHECKING:
+ from mypy_boto3_ec2.client import EC2Client
+else:
+ EC2Client = object
+
+
+def test_get_client_with_standard_retry() -> None:
+ with mock_ec2():
+ client: EC2Client = get_client_with_standard_retry("ec2")
+ assert client.describe_instances()["Reservations"] == []
diff --git a/source/app/tests/plugins/__init__.py b/source/app/tests/configuration/__init__.py
similarity index 100%
rename from source/app/tests/plugins/__init__.py
rename to source/app/tests/configuration/__init__.py
diff --git a/source/app/instance_scheduler/requesthandlers/admin_api_request_handler.py b/source/app/tests/configuration/setbuilders/__init__.py
similarity index 100%
rename from source/app/instance_scheduler/requesthandlers/admin_api_request_handler.py
rename to source/app/tests/configuration/setbuilders/__init__.py
diff --git a/source/app/tests/configuration/setbuilders/test_month_setbuilder.py b/source/app/tests/configuration/setbuilders/test_month_setbuilder.py
new file mode 100644
index 00000000..817f9577
--- /dev/null
+++ b/source/app/tests/configuration/setbuilders/test_month_setbuilder.py
@@ -0,0 +1,26 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import calendar
+
+from instance_scheduler.configuration.setbuilders.month_setbuilder import (
+ MonthSetBuilder,
+)
+
+
+def test_month_names() -> None:
+ # abbreviations, case-insensitive
+ for i, name in enumerate(calendar.month_abbr[1:]):
+ assert MonthSetBuilder().build(name) == {i + 1}
+ assert MonthSetBuilder().build(name.lower()) == {i + 1}
+ assert MonthSetBuilder().build(name.upper()) == {i + 1}
+
+ # full names, case-insensitive
+ for i, name in enumerate(calendar.month_name[1:]):
+ assert MonthSetBuilder().build(name) == {i + 1}
+ assert MonthSetBuilder().build(name.lower()) == {i + 1}
+ assert MonthSetBuilder().build(name.upper()) == {i + 1}
+
+
+def test_months_as_integers() -> None:
+ for i in range(1, 13): # 13 is exclusive, so this is 1-12
+ assert MonthSetBuilder().build(str(i)) == {i}
diff --git a/source/app/tests/configuration/setbuilders/test_monthday_setbuilder.py b/source/app/tests/configuration/setbuilders/test_monthday_setbuilder.py
new file mode 100644
index 00000000..f414837f
--- /dev/null
+++ b/source/app/tests/configuration/setbuilders/test_monthday_setbuilder.py
@@ -0,0 +1,98 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import calendar
+
+from pytest import raises
+
+from instance_scheduler.configuration.setbuilders.monthday_setbuilder import (
+ MonthdaySetBuilder,
+)
+
+
+# Documented behavior in the IG on 7/10/23
+#
+# Enter a comma-delimited list of days of the month, or a hyphenated range of days, during which the instance will run.
+# For example, enter 1, 2, 3 or 1-3 to run an instance during the first three days of the month.
+# You can also enter multiple ranges.
+# For example, enter 1-3, 7-9 to run an instance from the 1st to the 3rd and the 7th through the 9th.
+#
+# You can also schedule an instance to run every nth day of the month or every nth day of the month in a range.
+# For example, enter 1/7 to run an instance every seventh day starting on the 1st.
+# Enter 1-15/2 to run an instance every other day from the 1st to the 15th.
+#
+# Enter L to run an instance on the last day of the month.
+# Enter a date and W to run an instance on the nearest weekday to the specified date.
+# For example, enter 15W to run an instance on the nearest weekday to the 15th.
+def test_single_day_by_integer() -> None:
+ years = [2016, 2017] # leap and normal year
+
+ for year in years:
+ for month in range(1, 13):
+ _, days = calendar.monthrange(year, month)
+
+ for day in range(1, days):
+ assert MonthdaySetBuilder(year, month).build(str(day)) == {day}
+
+
+def test_single_range() -> None:
+ assert MonthdaySetBuilder(2023, 7).build("5-9") == {5, 6, 7, 8, 9}
+
+
+def test_multiple_ranges() -> None:
+ assert MonthdaySetBuilder(2023, 7).build("13-15, 26-27, 29") == {
+ 13,
+ 14,
+ 15,
+ 26,
+ 27,
+ 29,
+ }
+
+
+def test_every_nth_day() -> None:
+ assert MonthdaySetBuilder(2023, 7).build("1/7") == {1, 8, 15, 22, 29}
+ assert MonthdaySetBuilder(2023, 7).build("5/14") == {5, 19}
+
+
+def test_every_n_days_in_range() -> None:
+ assert MonthdaySetBuilder(2023, 7).build("1-10/2") == {1, 3, 5, 7, 9}
+ assert MonthdaySetBuilder(2023, 7).build("15-30/3") == {15, 18, 21, 24, 27, 30}
+
+
+def test_L_wildcard_returns_last_day_of_each_month() -> None:
+ years = [2016, 2017] # leap and normal year
+
+ for year in years:
+ for month in range(1, 13):
+ _, days = calendar.monthrange(year, month)
+ assert MonthdaySetBuilder(year, month).build("L") == {days}
+
+
+def test_W_wildcard_returns_nearest_weekday_in_same_month() -> None:
+ years = [2016, 2017] # leap and normal year
+
+ for year in years:
+ for month in range(1, 13):
+ _, days = calendar.monthrange(year, month)
+
+ for day in range(1, days):
+ weekday = calendar.weekday(year, month, day)
+ result = day
+ if (
+ weekday == 5
+ ): # Saturdays return the prev friday unless doing so would be a diff month
+ result = day - 1 if day > 1 else day + 2
+ elif (
+ weekday == 6
+ ): # Sundays return the next monday unless doing so would be a diff month
+ result = day + 1 if day < days else day - 2
+
+ assert MonthdaySetBuilder(year, month).build(str(day) + "W") == {result}
+
+
+def test_exceptions() -> None:
+ for h in range(13, 25):
+ with raises(ValueError):
+ MonthdaySetBuilder(2016, 1).build("W")
+ with raises(ValueError):
+ MonthdaySetBuilder(2016, 1).build("32W")
diff --git a/source/app/tests/configuration/setbuilders/test_setbuilder.py b/source/app/tests/configuration/setbuilders/test_setbuilder.py
new file mode 100644
index 00000000..30ae5e57
--- /dev/null
+++ b/source/app/tests/configuration/setbuilders/test_setbuilder.py
@@ -0,0 +1,273 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import string
+from collections.abc import Sequence
+from typing import Optional
+
+from pytest import raises
+
+from instance_scheduler.configuration.setbuilders.setbuilder import SetBuilder
+
+characters = string.ascii_lowercase
+names = [c * 3 for c in characters]
+names_cased = [n.capitalize() for n in names]
+all_items = set([i for i in range(0, len(names))])
+
+
+def test_name() -> None:
+ # names 1 char
+ for i, name in enumerate(names):
+ assert SetBuilder(names=names).build(name) == {i}
+ # names 1 char with offset
+ for i, name in enumerate(names):
+ assert SetBuilder(names=names, offset=1).build(name) == {i + 1}
+
+ # names 1 char ignore case
+ for i, name in enumerate(names):
+ assert SetBuilder(names=names, ignorecase=True).build(name.upper()) == {i}
+
+ # names 3
+ for i, name in enumerate(names_cased):
+ assert SetBuilder(names=names_cased).build(name) == {i}
+
+ # names 3, ignore case
+ for i, name in enumerate(names):
+ assert SetBuilder(names=names_cased, ignorecase=True).build(name) == {i}
+
+ # names 3, 1 significant character
+ for i, name in enumerate(names):
+ assert SetBuilder(names=names_cased, significant_name_characters=1).build(
+ name.upper()
+ ) == {i}
+
+ # names 3, 1 significant character, ignore case
+ for i, name in enumerate(names):
+ assert SetBuilder(names=names_cased, significant_name_characters=3).build(
+ name + name
+ ) == {i}
+
+ # all items passed in as list of strings
+ assert SetBuilder(names=names).build(names) == all_items
+
+
+def test_value() -> None:
+ # all by value
+ for value in range(0, len(names)):
+ assert SetBuilder(names=names).build(str(value)) == {value}
+
+ # all by value with offset
+ for value in range(1, len(names) + 1):
+ assert SetBuilder(names=names, offset=1).build(str(value)) == {value}
+
+
+def test_min_max() -> None:
+ # builder initialized by min and max values
+ for i in range(0, 5):
+ assert SetBuilder(min_value=0, max_value=4).build(str(i)) == {i}
+
+
+def test_wildcards() -> None:
+ # all items using standard and custom wildcard
+ assert SetBuilder(names).build("*") == all_items
+ assert SetBuilder(names).build("?") == all_items
+ assert SetBuilder(names, all_items_wildcards="!").build("!") == all_items
+
+ # first item using standard and custom wildcard
+ assert SetBuilder(names).build("^") == {0}
+ assert SetBuilder(names, first_item_wildcard="!").build("!") == {0}
+ assert SetBuilder(names, offset=1).build("^") == {1}
+
+ # last item using standard and custom wildcard
+ assert SetBuilder(names).build("$") == {len(names) - 1}
+ assert SetBuilder(names, last_item_wildcard="!").build("!") == {len(names) - 1}
+ assert SetBuilder(names, offset=1).build("$") == {len(names)}
+
+ # combined first and last wildcard
+ assert SetBuilder(names).build("^,$") == {0, len(names) - 1}
+ assert SetBuilder(names).build("^-$") == all_items
+
+
+def test_multiple() -> None:
+ # comma separated list of names
+ assert SetBuilder(names).build(",".join(names)) == all_items
+ # comma separated list of values
+ assert (
+ SetBuilder(names).build(",".join([str(i) for i in range(0, len(names))]))
+ == all_items
+ )
+
+
+def test_ranges() -> None:
+ # name range
+ assert SetBuilder(names).build(names[0] + "-" + names[2]) == {0, 1, 2}
+ # name ranges no overlap
+ assert SetBuilder(names).build(
+ names[0] + "-" + names[2] + "," + names[4] + "-" + names[6]
+ ) == {0, 1, 2, 4, 5, 6}
+ # name ranges with overlap
+ assert SetBuilder(names).build(
+ names[2] + "-" + names[6] + "," + names[4] + "-" + names[8]
+ ) == {2, 3, 4, 5, 6, 7, 8}
+ # name range with wrap
+ assert SetBuilder(names, wrap=True).build(names[-2] + "-" + names[2]) == {
+ 0,
+ 1,
+ 2,
+ len(names) - 2,
+ len(names) - 1,
+ }
+
+ # value range
+ assert SetBuilder(names).build("0-2") == {0, 1, 2}
+ # value ranges
+ assert SetBuilder(names).build("0-3, 9-12") == {0, 1, 2, 3, 9, 10, 11, 12}
+ # value ranges with overlap
+ assert SetBuilder(names).build("0-8, 6-12") == {
+ 0,
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ 12,
+ }
+ # value range with wrap
+ assert SetBuilder(names, wrap=True).build(str(len(names) - 2) + "-2") == {
+ 0,
+ 1,
+ 2,
+ len(names) - 2,
+ len(names) - 1,
+ }
+
+ with raises(ValueError):
+ SetBuilder(names, wrap=False).build(names[1] + "-" + names[0])
+
+ with raises(ValueError):
+ SetBuilder(names, wrap=False).build("2-1")
+
+
+def test_increments() -> None:
+ # increments on start name and value
+ assert SetBuilder(names).build(names[0] + "/5") == {
+ i for i in range(0, len(names), 5)
+ }
+ assert SetBuilder(names).build("0/3") == {i for i in range(0, len(names), 3)}
+
+ # increment on ranges
+ assert SetBuilder(names).build(names[0] + "-" + names[10] + "/2") == {
+ 0,
+ 2,
+ 4,
+ 6,
+ 8,
+ 10,
+ }
+ assert SetBuilder(names).build("0-10/3") == {0, 3, 6, 9}
+ assert SetBuilder(names, wrap=True).build("10-5/5") == {10, 15, 20, 25, 4}
+
+ # invalid increment numbers
+ with raises(ValueError):
+ SetBuilder(names).build("0/0")
+
+ with raises(ValueError):
+ SetBuilder(names).build("0/!")
+
+
+def test_unknown_values() -> None:
+ # unknown name raises error
+ with raises(ValueError):
+ SetBuilder(names).build("##")
+
+ # unknown value raises error
+ with raises(ValueError):
+ SetBuilder(min_value=0, max_value=1).build("-1")
+
+ # this class has a handler for handling unknow items
+ class SetBuilderWithHandler(SetBuilder):
+ def _parse_unknown(self, s: str) -> Optional[list[int]]:
+ return [] if s == "" else None
+
+ assert SetBuilderWithHandler(names).build("") == set()
+
+ with raises(ValueError):
+ SetBuilderWithHandler(names).build("unknown")
+
+
+def test_custom_parsers() -> None:
+ class SetBuilderWithCustomPreParser(SetBuilder):
+ def __init__(self, names: Sequence[str]):
+ SetBuilder.__init__(self, names=names)
+ self._pre_custom_parsers = [self._pre_parser]
+
+ def _pre_parser(self, s: str) -> Optional[list[int]]:
+ if s == "###":
+ return [0]
+ return None
+
+ assert SetBuilderWithCustomPreParser("").build("###") == {0}
+
+ class SetBuilderWithCustomPostParser(SetBuilder):
+ def __init__(self, names: Sequence[str]):
+ SetBuilder.__init__(self, names=names)
+ self._post_custom_parsers = [self._post_parser]
+
+ def _post_parser(self, s: str) -> Optional[list[int]]:
+ if s == "!!!":
+ return [1]
+ return None
+
+ assert SetBuilderWithCustomPostParser("").build("!!!") == {1}
+
+ class SetBuilderWithCustomParsers(SetBuilder):
+ def __init__(self, names: Sequence[str]):
+ SetBuilder.__init__(self, names=names)
+ self._post_custom_parsers = [self._pre_parser, self._post_parser]
+
+ def _pre_parser(self, s: str) -> Optional[list[int]]:
+ if s == "###":
+ return [99]
+ return None
+
+ def _post_parser(self, s: str) -> Optional[list[int]]:
+ if s == "!!!":
+ return [100]
+ return None
+
+ assert SetBuilderWithCustomParsers(names).build("###,!!!," + names[0]) == {
+ 0,
+ 99,
+ 100,
+ }
+
+
+def test_exceptions() -> None:
+ # names and max_value combination not allowed
+ with raises(ValueError):
+ SetBuilder(names=names, max_value=1)
+
+ # names and min_value combination not allowed
+ with raises(ValueError):
+ SetBuilder(names=names, min_value=0)
+
+ # both min_value and max_value must be used
+ with raises(ValueError):
+ SetBuilder(min_value=0)
+
+ # both min_value and max_value must be used
+ with raises(ValueError):
+ SetBuilder(max_value=1)
+
+ # max_value must be equal or greater than min_value
+ with raises(ValueError):
+ SetBuilder(min_value=99, max_value=1)
+
+ # offset must be the same if specified with min_value
+ with raises(ValueError):
+ SetBuilder(min_value=0, max_value=1, offset=1)
diff --git a/source/app/tests/configuration/setbuilders/test_weekday_setbuilder.py b/source/app/tests/configuration/setbuilders/test_weekday_setbuilder.py
new file mode 100644
index 00000000..283f2393
--- /dev/null
+++ b/source/app/tests/configuration/setbuilders/test_weekday_setbuilder.py
@@ -0,0 +1,167 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import calendar
+
+from pytest import raises
+
+from instance_scheduler.configuration.setbuilders.weekday_setbuilder import (
+ WeekdaySetBuilder,
+)
+
+
+# Documented behavior in the IG on 7/10/23
+#
+# Enter a comma-delimited list of days of the week, or a range of days of the week,
+# during which the instance will run. For example, enter 0, 1, 2 or 0-2 to run an instance Monday through Wednesday.
+# You can also enter multiple ranges. For example, enter 0-2, 4-6 to run an instance every day except Thursday.
+#
+# You can also schedule an instance to run every nth occurrence of a weekday in the month.
+# For example, enter Mon#1 or 0#1 to run an instance the first Monday of the month.
+#
+# Enter a day and L to run an instance on the last occurrence of that weekday in the month.
+# For example, enter friL or 4L to run an instance on the last Friday of the month.
+def test_char_sentry_value_snapshot() -> None:
+ assert WeekdaySetBuilder.WEEKDAY_NUMBER_CHAR == "#"
+ assert WeekdaySetBuilder.LAST_DAY_WILDCARD == "L"
+
+
+def test_day_names_and_abbreviations_map_correctly() -> None:
+ # ie. mon, tue, wed
+ for i, day_name in enumerate(calendar.day_abbr):
+ print(f"{day_name} = {i}")
+ assert WeekdaySetBuilder().build(day_name) == {i}
+
+ for i, day_name in enumerate(calendar.day_name):
+ print(f"{day_name} = {i}")
+ assert WeekdaySetBuilder().build(day_name) == {i}
+
+
+def test_providing_single_day_as_int_maps_correctly() -> None:
+ # ie. 1, 3, 5
+ for i in range(0, len(calendar.day_abbr) - 1):
+ assert WeekdaySetBuilder().build(str(i)) == {i}
+
+
+def test_weekday_numbered() -> None:
+ for year in [2016, 2017]:
+ for month in range(1, 13):
+ weekday, days_in_month = calendar.monthrange(year, month)
+
+ for day in range(1, days_in_month + 1):
+ num = int((day - 1) / 7) + 1
+ builder = WeekdaySetBuilder(year=year, month=month, day=day)
+
+ tested_by_name = builder.build(
+ calendar.day_abbr[weekday] + "#" + str(num)
+ )
+ assert tested_by_name == {weekday}
+
+ tested_by_value = builder.build(str(weekday) + "#" + str(num))
+ assert tested_by_value == {weekday}
+
+ for other_weekday in range(0, 7):
+ if other_weekday != weekday:
+ tested_by_name = builder.build(
+ calendar.day_abbr[other_weekday] + "#" + str(num)
+ )
+ assert tested_by_name == set()
+ tested_by_value = builder.build(
+ str(other_weekday) + "#" + str(num)
+ )
+ assert tested_by_value == set()
+
+ for other_num in range(1, 6):
+ if num != other_num:
+ tested_by_name = builder.build(
+ calendar.day_abbr[weekday] + "#" + str(other_num)
+ )
+ assert tested_by_name == set()
+ tested_by_value = builder.build(
+ str(weekday) + "#" + str(other_num)
+ )
+ assert tested_by_value == set()
+
+ weekday = (weekday + 1) % 7
+
+
+def test_last_monday_returns_expected_day() -> None:
+ # last 7 days of june 2023
+ assert (
+ WeekdaySetBuilder(year=2023, month=6, day=19).build("monL") == set()
+ ) # 2nd-to-last monday
+ assert WeekdaySetBuilder(year=2023, month=6, day=24).build("monL") == set() # sat
+ assert WeekdaySetBuilder(year=2023, month=6, day=25).build("monL") == set() # sun
+ assert WeekdaySetBuilder(year=2023, month=6, day=26).build("monL") == {0} # mon
+ assert WeekdaySetBuilder(year=2023, month=6, day=27).build("monL") == set() # tue
+ assert WeekdaySetBuilder(year=2023, month=6, day=28).build("monL") == set() # wed
+ assert WeekdaySetBuilder(year=2023, month=6, day=29).build("monL") == set() # thur
+ assert WeekdaySetBuilder(year=2023, month=6, day=30).build("monL") == set() # fri
+
+
+def test_last_tuesday_returns_expected_day() -> None:
+ # last 7 days of june
+ assert (
+ WeekdaySetBuilder(year=2023, month=6, day=20).build("monL") == set()
+ ) # 2nd-to-last tuesday
+ assert WeekdaySetBuilder(year=2023, month=6, day=24).build("tueL") == set() # sat
+ assert WeekdaySetBuilder(year=2023, month=6, day=25).build("tueL") == set() # sun
+ assert WeekdaySetBuilder(year=2023, month=6, day=26).build("tueL") == set() # mon
+ assert WeekdaySetBuilder(year=2023, month=6, day=27).build("tueL") == {1} # tue
+ assert WeekdaySetBuilder(year=2023, month=6, day=28).build("tueL") == set() # wed
+ assert WeekdaySetBuilder(year=2023, month=6, day=29).build("tueL") == set() # thur
+ assert WeekdaySetBuilder(year=2023, month=6, day=30).build("tueL") == set() # fri
+
+
+def test_last_day_wildcard_on_all_days_in_year() -> None:
+ for year in [2016, 2017]:
+ for month in range(1, 13):
+ weekday, days_in_month = calendar.monthrange(year, month)
+ for tested_on_day in range(1, days_in_month + 1):
+ builder = WeekdaySetBuilder(year=year, month=month, day=tested_on_day)
+
+ # test by name of weekday
+ day_num_l = calendar.day_abbr[weekday] + "L"
+ tested_by_name = builder.build(day_num_l)
+ # test by number of weekday
+ day_value_l = str(weekday) + "L"
+ tested_by_value = builder.build(day_value_l)
+
+ # everything before last week should be empty set
+ if tested_on_day <= (days_in_month - 7):
+ assert tested_by_name == set()
+ assert tested_by_value == set()
+
+ else:
+ # in last week the set should contain the day
+ assert tested_by_name == {weekday}
+ assert tested_by_value == {weekday}
+
+ # test if ofther weekdays on that day return empty set
+ for d in range(0, 6):
+ if d != weekday:
+ day_num_l = calendar.day_abbr[d] + "L"
+ day_value_l = str(d) + "L"
+ assert builder.build(day_num_l) == set()
+ assert builder.build(day_value_l) == set()
+
+ weekday = (weekday + 1) % 7
+
+
+def test_last_xday_tag_throws_exception_when_current_date_not_provided() -> None:
+ # L needs year, month and daya params
+ with raises(ValueError):
+ WeekdaySetBuilder().build("1L")
+
+
+def test_nth_weekday_throws_exception_when_n_is_gte_6() -> None:
+ # It is an oxymoron to ask for the 6th friday in the month as
+ # there can only ever be at most 5 of a given day each month
+ with raises(ValueError):
+ WeekdaySetBuilder(year=2016, month=10, day=4).build("0#6")
+
+
+def test_nth_weekday_throws_exception_when_n_is_lte_0() -> None:
+ with raises(ValueError):
+ WeekdaySetBuilder(year=2023, month=7, day=10).build("0#-1")
+ with raises(ValueError):
+ WeekdaySetBuilder(year=2016, month=10, day=4).build("0#0")
diff --git a/source/app/tests/configuration/test_config_admin.py b/source/app/tests/configuration/test_config_admin.py
new file mode 100644
index 00000000..d12e2b5b
--- /dev/null
+++ b/source/app/tests/configuration/test_config_admin.py
@@ -0,0 +1,196 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import json
+from datetime import date, datetime
+
+from pytest import raises
+
+from instance_scheduler.configuration import config_admin
+from instance_scheduler.configuration.config_admin import (
+ ConfigAdmin,
+ ConfigTableScheduleItem,
+)
+from instance_scheduler.util.app_env import AppEnv
+
+
+def test_error_strings() -> None:
+ assert config_admin.ERR_PERIOD_BEGIN_LATER_THAN_END == (
+ "error: period begintime {} can not be later than endtime {}"
+ )
+ assert (
+ config_admin.ERR_SCHEDULE_INVALID_OVERRIDE
+ == "{} is not a valid value for {}, possible values are {}"
+ )
+ assert config_admin.ERR_SCHEDULE_OVERWRITE_OVERRIDE_EXCLUSIVE == (
+ "{} option is mutually exclusive with {} option"
+ )
+ assert config_admin.ERR_CREATE_PERIOD_EXISTS == "error: period {} already exists"
+ assert (
+ config_admin.ERR_CREATE_SCHEDULE_EXISTS == "error: schedule {} already exists"
+ )
+ assert config_admin.ERR_DEL_PERIOD_IN_USE == (
+ "error: period {} can not be deleted because it is still used in schedule(s) {}"
+ )
+ assert config_admin.ERR_PERIOD_NOT_FOUND == "not found: period {} does not exist"
+ assert (
+ config_admin.ERR_DEL_SCHEDULE_NAME_EMPTY
+ == "error: schedule name parameter can not be empty"
+ )
+ assert (
+ config_admin.ERR_SCHEDULE_NOT_FOUND == "not found: schedule {} does not exist"
+ )
+ assert (
+ config_admin.ERR_EMPTY_PERIOD_NAME
+ == "error: period name parameter can not be empty"
+ )
+ assert (
+ config_admin.ERR_GET_SCHEDULE_NAME_EMPTY
+ == "error: error schedule name parameter can not be empty"
+ )
+ assert config_admin.ERR_GET_USAGE_INVALID_END_DATE == (
+ "error: invalid enddate {}, must be a valid date in format yyyymmdd {}"
+ )
+ assert config_admin.ERR_GET_USAGE_INVALID_START_DATE == (
+ "error: invalid startdate {}, must be a valid date in format yyyymmdd {}"
+ )
+ assert config_admin.ERR_GET_USAGE_SCHEDULE_NAME_EMPTY == (
+ "error: error schedule name parameter can not be empty"
+ )
+ assert config_admin.ERR_GET_USAGE_START_MUST_BE_LESS_OR_EQUAL_STOP == (
+ "stop_date must be equal or later than start_date"
+ )
+ assert config_admin.ERR_NAME_PARAM_MISSING == "error: name parameter is missing"
+ assert (
+ config_admin.ERR_NO_PERIODS
+ == "error: at least one period condition must be specified"
+ )
+ assert (
+ config_admin.ERR_PERIOD_INVALID_MONTHDAYS
+ == "error: {} is not a valid month days specification"
+ )
+ assert (
+ config_admin.ERR_PERIOD_INVALID_MONTHS
+ == "error: {} is not a valid months specification"
+ )
+ assert config_admin.ERR_PERIOD_INVALID_TIME == "error: {} {} is not a valid time"
+ assert (
+ config_admin.ERR_PERIOD_INVALID_WEEKDAYS
+ == "error: {} is not a valid weekdays specification {}"
+ )
+ assert config_admin.ERR_PERIOD_UNKNOWN_PARAMETER == (
+ "error: {} is not a valid parameter, valid parameters are {}"
+ )
+ assert (
+ config_admin.ERR_SCHEDULE_INVALID_BOOLEAN
+ == "error: {} for parameter {} is not a valid boolean value"
+ )
+ assert (
+ config_admin.ERR_SCHEDULE_INVALID_TIMEZONE
+ == "error: {} is not a valid time zone for parameter {}"
+ )
+ assert config_admin.ERR_SCHEDULE_NAME_MISSING == "error: name parameter is missing"
+ assert (
+ config_admin.ERR_SCHEDULE_NO_PERIOD
+ == "error: at least one period must be specified for a schedule"
+ )
+ assert (
+ config_admin.ERR_SCHEDULE_PERIOD_DOES_NOT_EXISTS
+ == "error: not found: period {} does not exist"
+ )
+ assert config_admin.ERR_SCHEDULE_UNKNOWN_PARAMETER == (
+ "error: {} is not a valid parameter, valid parameters are {}"
+ )
+ assert config_admin.ERR_UPDATE_INVALID_BOOL_PARAM == (
+ "error: {} for parameter {} is not a valid boolean value"
+ )
+ assert (
+ config_admin.ERR_UPDATE_INVALID_TZ_PARAMETER
+ == "error: {} is not a valid time zone for parameter {}"
+ )
+ assert (
+ config_admin.ERR_UPDATE_SCHEDULE_NAME_EMPTY
+ == "error: schedule name parameter can not be empty"
+ )
+ assert (
+ config_admin.ERR_UPDATE_TAGNAME_EMPTY
+ == "error: tagname parameter must be specified"
+ )
+ assert (
+ config_admin.ERR_UPDATE_UNKNOWN_PARAMETER
+ == "error: {} is not a valid parameter"
+ )
+ assert config_admin.ERR_UPDATE_UNKNOWN_SERVICE == "{} is not a supported service"
+ assert config_admin.ERR_STOP_MUST_BE_LATER_OR_EQUAL_TO_START == (
+ "stop_date must be equal or later than start_date"
+ )
+
+
+def test_info_strings() -> None:
+ assert config_admin.INF_ADD_ACCOUNT_EVENT_PERMISSION == (
+ "Add permission for account {} to put events on message bus, sid is {}"
+ )
+ assert config_admin.INF_REMOVE_EVENT_PERMISSION == (
+ "Remove permission for account {} to put events on event bus, sid = {}"
+ )
+
+
+def test_config_admin_type_attr() -> None:
+ assert ConfigAdmin.TYPE_ATTR == "type"
+
+
+def test_config_admin_time_regex() -> None:
+ assert ConfigAdmin.TIME_REGEX == "^([0|1]?[0-9]|2[0-3]):[0-5][0-9]$"
+
+
+def test_config_admin_supported_services() -> None:
+ assert ConfigAdmin.SUPPORTED_SERVICES == ["ec2", "rds"]
+
+
+def test_config_admin_table_name(app_env: AppEnv) -> None:
+ assert ConfigAdmin(None, None).table_name == app_env.config_table_name
+
+
+def test_custom_encoder_set() -> None:
+ """Stringifies set as list"""
+ assert json.dumps(set(), cls=ConfigAdmin.CustomEncoder) == "[]"
+
+ items = [1, 2, 3]
+ items_set = set(items)
+ result = json.loads(json.dumps(items_set, cls=ConfigAdmin.CustomEncoder))
+ assert isinstance(result, list)
+ assert items_set == set(result)
+
+
+def test_custom_encoder_datetime() -> None:
+ """Stringifies datetimes in locale format without seconds"""
+ dt_with_seconds = datetime(
+ year=2023, month=5, day=11, hour=11, minute=41, second=20
+ )
+ dt_no_seconds = dt_with_seconds.replace(second=0)
+ expected_str = f'"{dt_no_seconds.strftime("%x %X")}"'
+ assert json.dumps(dt_with_seconds, cls=ConfigAdmin.CustomEncoder) == expected_str
+
+
+def test_custom_encoder_invalid() -> None:
+ """Errors on other types"""
+ with raises(TypeError):
+ json.dumps(date(year=2023, month=1, day=12), cls=ConfigAdmin.CustomEncoder)
+
+
+def test_validate_schedule_no_periods() -> None:
+ config = ConfigAdmin(None, None)
+
+ with raises(ValueError) as err:
+ config._validate_schedule(ConfigTableScheduleItem(name="my-schedule"))
+
+ assert str(err.value) == config_admin.ERR_SCHEDULE_NO_PERIOD
+
+
+def test_validate_schedule_override_no_periods() -> None:
+ config = ConfigAdmin(None, None)
+ schedule = ConfigTableScheduleItem(name="my-schedule", override_status="running")
+
+ result = config._validate_schedule(schedule)
+
+ schedule["type"] = "schedule"
+ assert result == schedule
diff --git a/source/app/tests/configuration/test_configuration.py b/source/app/tests/configuration/test_configuration.py
index c1e0b832..50ed97fd 100644
--- a/source/app/tests/configuration/test_configuration.py
+++ b/source/app/tests/configuration/test_configuration.py
@@ -1,27 +1,39 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-import os
-from unittest.mock import patch
-from instance_scheduler import configuration
-
+from unittest.mock import MagicMock, patch
+from zoneinfo import ZoneInfo
-def test_env_var_names():
- assert configuration.ENV_CONFIG == "CONFIG_TABLE"
- assert configuration.ENV_STATE == "STATE_TABLE"
- assert configuration.ENV_ACCOUNT == "ACCOUNT"
+from instance_scheduler import configuration
+from instance_scheduler.configuration.scheduler_config import GlobalConfig
+from instance_scheduler.util.app_env import AppEnv
+
+mock_config = GlobalConfig(
+ scheduled_services=["ec2"],
+ schedule_clusters=True,
+ tag_name="tag",
+ regions=["us-east-1"],
+ default_timezone=ZoneInfo("UTC"),
+ schedules={},
+ trace=False,
+ enable_ssm_maintenance_windows=True,
+ use_metrics=True,
+ remote_account_ids=["123456789012"],
+ namespace="ns",
+ aws_partition="aws",
+ scheduler_role_name="rolename",
+ organization_id="",
+ schedule_lambda_account=False,
+ create_rds_snapshot=True,
+ started_tags="",
+ stopped_tags="",
+)
+
+
+def test_env_var_names() -> None:
assert configuration.ENV_STACK == "STACK_NAME"
- assert configuration.ENV_TAG_NAME == "TAG_NAME"
- assert configuration.ENV_SCHEDULE_FREQUENCY == "SCHEDULER_FREQUENCY"
- assert configuration.ENV_TRACE == "TRACE"
- assert (
- configuration.ENV_ENABLE_SSM_MAINTENANCE_WINDOWS
- == "ENABLE_SSM_MAINTENANCE_WINDOWS"
- )
- assert configuration.ENV_USER_AGENT == "USER_AGENT"
- assert configuration.ENV_SCHEDULER_RULE == "SCHEDULER_RULE"
-def test_month_names():
+def test_month_names() -> None:
assert configuration.MONTH_NAMES == [
"jan",
"feb",
@@ -38,7 +50,7 @@ def test_month_names():
]
-def test_weekday_names():
+def test_weekday_names() -> None:
assert configuration.WEEKDAY_NAMES == [
"mon",
"tue",
@@ -50,23 +62,23 @@ def test_weekday_names():
]
-def test_switch_values():
+def test_switch_values() -> None:
assert configuration.SWITCH_VALUES == ["off", "on"]
-def test_defaults():
+def test_defaults() -> None:
assert configuration.DEFAULT_TZ == "UTC"
assert configuration.DEFAULT_TAGNAME == "Schedule"
-def test_time_format_string():
+def test_time_format_string() -> None:
assert configuration.TIME_FORMAT_STRING == "%H:%M"
-def test_attributes():
+def test_attributes() -> None:
assert configuration.TRACE == "trace"
assert (
- configuration.ENABLE_SSM_MAINTENANCE_WINDOWS == "enable_SSM_maintenance_windows"
+ configuration.ENABLE_SSM_MAINTENANCE_WINDOWS == "enable_ssm_maintenance_windows"
)
assert configuration.METRICS == "use_metrics"
assert configuration.REGIONS == "regions"
@@ -101,7 +113,7 @@ def test_attributes():
assert configuration.SCHEDULE_CONFIG_STACK == "configured_in_stack"
-def test_override_status():
+def test_override_status() -> None:
assert configuration.OVERRIDE_STATUS_STOPPED == "stopped"
assert configuration.OVERRIDE_STATUS_RUNNING == "running"
assert configuration.OVERRIDE_STATUS_VALUES == [
@@ -110,11 +122,11 @@ def test_override_status():
]
-def test_instance_type_separator():
+def test_instance_type_separator() -> None:
assert configuration.INSTANCE_TYPE_SEP == "@"
-def test_tag_values():
+def test_tag_values() -> None:
assert configuration.TAG_VAL_SCHEDULER == "scheduler"
assert configuration.TAG_VAL_MINUTE == "minute"
assert configuration.TAG_VAL_HOUR == "hour"
@@ -124,42 +136,41 @@ def test_tag_values():
assert configuration.TAG_VAL_TIMEZONE == "timezone"
-def test_configuration_global():
- assert configuration.__configuration == None
+def test_configuration_global() -> None:
+ assert configuration.__configuration is None
@patch("instance_scheduler.configuration.SchedulerConfigBuilder")
@patch("instance_scheduler.configuration.ConfigDynamodbAdapter")
def test_get_scheduler_configuration(
- mock_config_dynamodb_adapter, mock_scheduler_config_builder
-):
+ mock_config_dynamodb_adapter: MagicMock,
+ mock_scheduler_config_builder: MagicMock,
+ app_env: AppEnv,
+) -> None:
my_configdata = "my config"
mock_config_dynamodb_adapter.return_value.config = my_configdata
- expected_configuration = "expected configuration"
+ expected_configuration = mock_config
mock_scheduler_config_builder.return_value.build.return_value = (
expected_configuration
)
- my_config_env = "my config env"
- with patch.dict(os.environ, {configuration.ENV_CONFIG: my_config_env}):
- result = configuration.get_scheduler_configuration(None)
- assert result == expected_configuration
+ result = configuration.get_global_configuration(None)
+ assert result == expected_configuration
assert configuration.__configuration == expected_configuration
- mock_config_dynamodb_adapter.assert_called_once_with(my_config_env)
+ mock_config_dynamodb_adapter.assert_called_once_with(app_env.config_table_name)
mock_scheduler_config_builder.assert_called_once_with(logger=None)
mock_scheduler_config_builder.return_value.build.assert_called_once_with(
my_configdata
)
-def test_get_scheduler_configuration_already_set():
- my_configuration = "my configuration"
- configuration.__configuration = my_configuration
- assert configuration.get_scheduler_configuration(None) == my_configuration
+def test_get_scheduler_configuration_already_set() -> None:
+ configuration.__configuration = mock_config
+ assert configuration.get_global_configuration(None) == mock_config
-def test_unload_scheduler_configuration():
- configuration.__configuration = {}
- configuration.unload_scheduler_configuration()
- assert configuration.__configuration == None
+def test_unload_scheduler_configuration() -> None:
+ configuration.__configuration = mock_config
+ configuration.unload_global_configuration()
+ assert configuration.__configuration is None
diff --git a/source/app/tests/test_configuration_module.py b/source/app/tests/configuration/test_configuration_module.py
similarity index 84%
rename from source/app/tests/test_configuration_module.py
rename to source/app/tests/configuration/test_configuration_module.py
index 9f43e8f4..2f195ddd 100644
--- a/source/app/tests/test_configuration_module.py
+++ b/source/app/tests/configuration/test_configuration_module.py
@@ -1,28 +1,19 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-from instance_scheduler.util.logger import Logger
import datetime
+
from instance_scheduler.configuration.scheduler_config_builder import (
SchedulerConfigBuilder,
)
+from instance_scheduler.util.app_env import AppEnv
+from tests.logger import MockLogger
-def test_scheduler_config_builder():
- LOG_STREAM = "{}-{:0>4d}{:0>2d}{:0>2d}"
- dt = datetime.datetime.utcnow()
- logstream = LOG_STREAM.format(
- "test_configuration_module", dt.year, dt.month, dt.day
- )
- logger = Logger(
- logstream=logstream,
- buffersize=30,
- context={},
- loggroup="test_configuration_module",
- )
+def test_scheduler_config_builder(app_env: AppEnv) -> None:
+ logger = MockLogger()
config_data = {
- "regions": {"us-east-1"},
- "scheduled_services": {"ec2"},
+ "regions": ["us-east-1"],
+ "scheduled_services": ["ec2"],
"stopped_tags": "ScheduleMessage=Stopped on {year}/{month}/{day} at {hour}:{minute} {timezone}",
"create_rds_snapshot": False,
"default_timezone": "US/Eastern",
@@ -237,48 +228,50 @@ def test_scheduler_config_builder():
],
}
response = SchedulerConfigBuilder(logger=logger).build(config_data)
- assert response.scheduled_services == {"ec2"}
- assert response.default_timezone == "US/Eastern"
- assert response.tag_name == "Schedule"
- assert response.create_rds_snapshot == False
- assert response.regions == {"us-east-1"}
+ assert set(response.scheduled_services) == set(app_env.scheduled_services())
+ assert response.default_timezone == app_env.default_timezone
+ assert response.tag_name == app_env.schedule_tag_key
+ assert response.create_rds_snapshot is app_env.enable_rds_snapshots
+ assert set(response.regions) == set(app_env.schedule_regions)
assert response.remote_account_ids == []
for schedule_name in response.schedules:
if schedule_name == "docDbSchedule":
- assert response.get_schedule(schedule_name).timezone == "US/Eastern"
- for period in response.get_schedule(schedule_name).periods:
+ schedule = response.get_schedule(schedule_name)
+ assert schedule is not None
+ assert schedule.timezone == "US/Eastern"
+ for period in schedule.periods:
valid_current_datetime = datetime.datetime(
2021, 6, 18, 14, 5, 59, 342380
)
assert (
- period.get("period").get_desired_state(
- logger, valid_current_datetime
- )
+ period["period"].get_desired_state(logger, valid_current_datetime)
== "running"
)
invalid_datetime = datetime.datetime(2021, 6, 20, 17, 30, 59, 34258)
assert (
- period.get("period").get_desired_state(logger, invalid_datetime)
+ period["period"].get_desired_state(logger, invalid_datetime)
== "stopped"
)
if schedule_name == "monstartandfridayend":
- assert response.get_schedule(schedule_name).timezone == "US/Pacific"
- for period in response.get_schedule(schedule_name).periods:
- if period.get("period").name == "tuethu":
+ schedule = response.get_schedule(schedule_name)
+ assert schedule is not None
+ assert schedule.timezone == "US/Pacific"
+ for period in schedule.periods:
+ if period["period"].name == "tuethu":
tuesday_nine_am = datetime.datetime(2021, 9, 14, 9, 0, 00, 0)
assert (
- period.get("period").get_desired_state(logger, tuesday_nine_am)
+ period["period"].get_desired_state(logger, tuesday_nine_am)
== "running"
)
- if period.get("period").name == "fridaystop":
+ if period["period"].name == "fridaystop":
friday_five_fifteen_pm = datetime.datetime(
2021, 9, 17, 17, 15, 00, 0
)
assert (
- period.get("period").get_desired_state(
+ period["period"].get_desired_state(
logger, friday_five_fifteen_pm
)
== "stopped"
@@ -287,7 +280,7 @@ def test_scheduler_config_builder():
2021, 9, 17, 16, 45, 00, 0
)
assert (
- period.get("period").get_desired_state(
+ period["period"].get_desired_state(
logger, friday_four_fortyfive_pm
)
== "running"
@@ -296,7 +289,7 @@ def test_scheduler_config_builder():
2021, 9, 18, 16, 45, 00, 0
)
assert (
- period.get("period").get_desired_state(
+ period["period"].get_desired_state(
logger, sat_four_fortyfive_pm
)
== "stopped"
@@ -305,7 +298,7 @@ def test_scheduler_config_builder():
2021, 9, 19, 16, 45, 00, 0
)
assert (
- period.get("period").get_desired_state(
+ period["period"].get_desired_state(
logger, sunday_four_fortyfive_pm
)
== "stopped"
diff --git a/source/app/tests/configuration/test_running_period.py b/source/app/tests/configuration/test_running_period.py
new file mode 100644
index 00000000..0382148c
--- /dev/null
+++ b/source/app/tests/configuration/test_running_period.py
@@ -0,0 +1,98 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import calendar
+from datetime import datetime
+
+from instance_scheduler.configuration.running_period import RunningPeriod
+from tests.logger import MockLogger
+
+
+def test_weekdays_only_is_running_on_specified_day() -> None:
+ period = RunningPeriod(name="name", weekdays={0, 3, 5})
+ # monday (0)
+ assert (
+ period.get_desired_state(MockLogger(), datetime(year=2023, month=7, day=10))
+ == "running"
+ )
+ # tuesday (1)
+ assert (
+ period.get_desired_state(MockLogger(), datetime(year=2023, month=7, day=11))
+ == "stopped"
+ )
+ # wednesday (2)
+ assert (
+ period.get_desired_state(MockLogger(), datetime(year=2023, month=7, day=12))
+ == "stopped"
+ )
+ # thursday (3)
+ assert (
+ period.get_desired_state(MockLogger(), datetime(year=2023, month=7, day=13))
+ == "running"
+ )
+ # friday (4)
+ assert (
+ period.get_desired_state(MockLogger(), datetime(year=2023, month=7, day=14))
+ == "stopped"
+ )
+ # saturday (5)
+ assert (
+ period.get_desired_state(MockLogger(), datetime(year=2023, month=7, day=15))
+ == "running"
+ )
+ # sunday (6)
+ assert (
+ period.get_desired_state(MockLogger(), datetime(year=2023, month=7, day=16))
+ == "stopped"
+ )
+
+
+def test_month_only_is_running_for_whole_month() -> None:
+ period = RunningPeriod(name="name", months={4})
+
+ _, days_in_month = calendar.monthrange(year=2023, month=4)
+ for month_day in range(1, days_in_month + 1):
+ assert (
+ period.get_desired_state(
+ MockLogger(), datetime(year=2023, month=4, day=month_day)
+ )
+ == "running"
+ ), f"failed for {month_day}"
+
+
+def test_month_only_is_stopped_in_other_months() -> None:
+ period = RunningPeriod(name="name", months={4})
+
+ for month in range(1, 13):
+ if month == 4:
+ continue
+ assert (
+ period.get_desired_state(
+ MockLogger(), datetime(year=2023, month=month, day=3)
+ )
+ == "stopped"
+ ), f"failed for {month}"
+
+
+def test_monthday_only_is_running_on_specific_monthdays() -> None:
+ period = RunningPeriod(name="name", monthdays={3, 5, 15})
+ for month_day in [3, 5, 15]:
+ assert (
+ period.get_desired_state(
+ MockLogger(), datetime(year=2023, month=4, day=month_day)
+ )
+ == "running"
+ ), f"failed for {month_day}"
+
+
+def test_monthday_only_is_stopped_on_other_monthdays() -> None:
+ period = RunningPeriod(name="name", monthdays={3, 5, 15})
+ _, days_in_month = calendar.monthrange(year=2023, month=4)
+ for month_day in range(1, days_in_month + 1):
+ if month_day in {3, 5, 15}:
+ continue # skip days it should be running
+ assert (
+ period.get_desired_state(
+ MockLogger(), datetime(year=2023, month=4, day=month_day)
+ )
+ == "stopped"
+ ), f"failed for {month_day}"
diff --git a/source/app/tests/configuration/test_scheduler_config.py b/source/app/tests/configuration/test_scheduler_config.py
new file mode 100644
index 00000000..2cef588b
--- /dev/null
+++ b/source/app/tests/configuration/test_scheduler_config.py
@@ -0,0 +1,30 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from instance_scheduler.configuration import scheduler_config
+
+
+def test_inf_scheduler_display() -> None:
+ assert scheduler_config.INF_SCHEDULE_DISPLAY == (
+ "Configuration:\n"
+ 'Scheduled services = "{}"\n'
+ 'Schedule clusters = "{}"\n'
+ 'Create RDS instance snapshot = "{}"\n'
+ 'Tagname = "{}"\n'
+ 'Default timezone = "{}"\n'
+ 'Trace = "{}"\n'
+ 'Enable SSM Maintenance Windows = "{}"\n'
+ 'Use metrics = "{}"\n'
+ 'Regions = "{}"\n'
+ 'Started tags = "{}"\n'
+ 'Stopped tags = "{}"\n'
+ 'Process Lambda account = "{}"\n'
+ 'Scheduler Role Name = "{}"\n'
+ 'Namespace = "{}"\n'
+ 'Organization Id = "{}"\n'
+ 'Aws Partition = "{}"\n'
+ 'Remote Account Ids = "{}"'
+ )
+
+
+def test_tag_val_str() -> None:
+ assert scheduler_config.TAG_VAL_STR == "{{{}}}"
diff --git a/source/app/tests/test_instance_schedule.py b/source/app/tests/configuration/test_scheduler_config_builder.py
similarity index 81%
rename from source/app/tests/test_instance_schedule.py
rename to source/app/tests/configuration/test_scheduler_config_builder.py
index 22fbf48b..ac842b7a 100644
--- a/source/app/tests/test_instance_schedule.py
+++ b/source/app/tests/configuration/test_scheduler_config_builder.py
@@ -1,25 +1,17 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-from instance_scheduler.util.logger import Logger
import datetime
+
+from instance_scheduler.configuration.instance_schedule import Instance
from instance_scheduler.configuration.scheduler_config_builder import (
SchedulerConfigBuilder,
)
-import collections
-import pytz
+from instance_scheduler.util.app_env import AppEnv
+from tests.logger import MockLogger
-def test_instance_schedule():
- LOG_STREAM = "{}-{:0>4d}{:0>2d}{:0>2d}"
- dt = datetime.datetime.utcnow()
- logstream = LOG_STREAM.format("test_instance_schedule", dt.year, dt.month, dt.day)
- logger = Logger(
- logstream=logstream,
- buffersize=30,
- context={},
- loggroup="test_configuration_module",
- )
+def test_instance_schedule(app_env: AppEnv) -> None:
+ logger = MockLogger()
config_data = {
"regions": {"us-east-1"},
"scheduled_services": {"ec2"},
@@ -200,11 +192,9 @@ def test_instance_schedule():
response = SchedulerConfigBuilder(logger=logger).build(config_data)
schedule = response.get_schedule("running")
- ec2Instance = collections.namedtuple(
- "ec2Instance",
- "id schedule_name name state state_name is_running is_terminated current_state instancetype tags account region service instance_str",
- )
- instance = ec2Instance(
+ assert schedule is not None
+
+ instance = Instance(
id="i-00bedf8a12df1dd6a",
schedule_name="stopped",
name="ISRelated",
@@ -219,31 +209,27 @@ def test_instance_schedule():
region="us-east-1",
service="ec2",
instance_str="EC2:i-00bedf8a12df1dd6a (ISRelated)",
+ allow_resize=True,
+ hibernate=False,
+ maintenance_window=None,
)
- try:
- inst_state, inst_type, valid_period = schedule.get_desired_state(
- instance, logger=logger
- )
- # current time this test is being executed.
- current_test_execution_time = datetime.datetime.now(pytz.timezone("US/Eastern"))
- # the configured period is a weekday mon-fri and time is between 9:00 AM and 5:00 PM.
- if current_test_execution_time.today().weekday() in [0, 1, 2, 3, 4]:
- if (
- current_test_execution_time.hour < 17
- and current_test_execution_time.hour > 9
- ):
- assert valid_period == "office-hours"
- assert inst_state == "running"
- else:
- assert valid_period == None
- assert inst_state == "stopped"
+ current_test_execution_time = datetime.datetime.now(app_env.default_timezone)
+ inst_state, _, valid_period = schedule.get_desired_state(
+ instance, current_test_execution_time, logger=logger
+ )
+
+ # the configured period is a weekday mon-fri and time is between 9:00 AM and 5:00 PM.
+ if current_test_execution_time.today().weekday() in [0, 1, 2, 3, 4]:
+ if (
+ current_test_execution_time.hour < 17
+ and current_test_execution_time.hour > 9
+ ):
+ assert valid_period == "office-hours"
+ assert inst_state == "running"
else:
- assert valid_period == None
+ assert valid_period is None
assert inst_state == "stopped"
-
- except Exception as error:
- print(error)
-
-
-test_instance_schedule()
+ else:
+ assert valid_period is None
+ assert inst_state == "stopped"
diff --git a/source/app/tests/configuration/test_scheduling_context.py b/source/app/tests/configuration/test_scheduling_context.py
new file mode 100644
index 00000000..552a0218
--- /dev/null
+++ b/source/app/tests/configuration/test_scheduling_context.py
@@ -0,0 +1,133 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import datetime
+from typing import Any
+from zoneinfo import ZoneInfo
+
+from instance_scheduler.configuration import scheduling_context
+from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler.configuration.running_period import RunningPeriod
+from instance_scheduler.configuration.running_period_dict_element import (
+ RunningPeriodDictElement,
+)
+from instance_scheduler.configuration.scheduling_context import (
+ SchedulingContext,
+ TagTemplate,
+)
+
+test_period_1 = RunningPeriod(
+ name="test-period-1",
+ begintime=datetime.time(9, 0, 0),
+ endtime=datetime.time(17, 0, 0),
+ weekdays={0, 1, 2, 3, 4},
+)
+
+test_schedule_1 = InstanceSchedule(
+ name="test-schedule-1",
+ timezone="UTC",
+ override_status=None,
+ use_metrics=True,
+ periods=[RunningPeriodDictElement(period=test_period_1, instancetype=None)],
+ retain_running=None,
+ enforced=False,
+ hibernate=False,
+ use_maintenance_window=False,
+ stop_new_instances=True,
+)
+
+test_schedule_2 = InstanceSchedule(
+ name="test-schedule-2",
+ timezone="UTC",
+ override_status=None,
+ use_metrics=True,
+ periods=[{"period": test_period_1, "instancetype": None}],
+ retain_running=None,
+ enforced=False,
+ hibernate=False,
+ use_maintenance_window=False,
+ stop_new_instances=True,
+)
+
+context = SchedulingContext(
+ account_id="111122223333",
+ schedule_lambda_account=True,
+ service="ec2",
+ region="us-east-1",
+ tag_name="Schedule",
+ current_dt=datetime.datetime.fromisoformat("2023-06-09T16:38:42.862261+00:00"),
+ default_timezone=ZoneInfo("UTC"),
+ schedules={"test-schedule-1": test_schedule_1, "test-schedule-2": test_schedule_2},
+ schedule_clusters=False,
+ trace=False,
+ enable_ssm_maintenance_windows=False,
+ use_metrics=False,
+ namespace="namespace",
+ aws_partition="aws",
+ scheduler_role_name="scheduler-role",
+ organization_id="",
+ create_rds_snapshot=False,
+ started_tags=[TagTemplate(Key="action", Value="started")],
+ stopped_tags=[TagTemplate(Key="action", Value="stopped")],
+)
+
+
+expectedOut: dict[str, Any] = {
+ "tag_name": "Schedule",
+ "default_timezone": "UTC",
+ "trace": False,
+ "namespace": "namespace",
+ "current_dt": "2023-06-09T16:38:42.862261+00:00",
+ "scheduler_role_name": "scheduler-role",
+ "organization_id": "",
+ "aws_partition": "aws",
+ "enable_ssm_maintenance_windows": False,
+ "use_metrics": False,
+ "schedule_clusters": False,
+ "create_rds_snapshot": False,
+ "schedule_lambda_account": True,
+ "started_tags": "action=started", # many of these are optional and not normally included in shape when none
+ "stopped_tags": "action=stopped",
+ "region": "us-east-1",
+ "service": "ec2",
+ "account_id": "111122223333",
+ "schedules": {
+ "test-schedule-1": {
+ "name": "test-schedule-1",
+ "timezone": "UTC",
+ "stop_new_instances": True,
+ "use_metrics": True,
+ "enforced": False,
+ "hibernate": False,
+ "use_maintenance_window": False,
+ "periods": ["test-period-1"],
+ },
+ "test-schedule-2": {
+ "name": "test-schedule-2",
+ "timezone": "UTC",
+ "stop_new_instances": True,
+ "use_metrics": True,
+ "enforced": False,
+ "hibernate": False,
+ "use_maintenance_window": False,
+ "periods": ["test-period-1"],
+ },
+ },
+ "periods": {
+ "test-period-1": {
+ "begintime": "09:00",
+ "endtime": "17:00",
+ "weekdays": [0, 1, 2, 3, 4],
+ },
+ },
+}
+
+
+def test_to_dict_matches_expected_event_format() -> None:
+ # print(context.to_dict())
+ assert context.to_dict() == expectedOut
+
+
+def test_result_of_from_dict_matches_original_object() -> None:
+ dict_representation = context.to_dict()
+ built_context = scheduling_context.from_dict(dict_representation)
+ assert context.to_dict() == built_context.to_dict()
diff --git a/source/app/tests/conftest.py b/source/app/tests/conftest.py
index d18be085..c8fc3555 100644
--- a/source/app/tests/conftest.py
+++ b/source/app/tests/conftest.py
@@ -1,44 +1,120 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
+from collections.abc import Iterator
+from os import environ
+from typing import TYPE_CHECKING
+from unittest.mock import patch
-from unittest import mock
-import os
-import pytest
import boto3
-from os import environ
-from moto import mock_dynamodb
-import sys
+from moto import mock_dynamodb, mock_ec2, mock_logs, mock_sns, mock_sts
+from pytest import fixture
+import instance_scheduler.util.app_env
+from instance_scheduler.configuration import unload_global_configuration
+from instance_scheduler.util.app_env import AppEnv
+from tests.util.test_app_env import env_from_app_env, example_app_env
-@pytest.fixture
-def aws_credentials():
- """Mocked AWS Credentials for moto"""
- environ["AWS_ACCESS_KEY_ID"] = "testing"
- environ["AWS_SECRET_ACCESS_KEY"] = "testing"
- environ["AWS_SECURITY_TOKEN"] = "testing"
- environ["AWS_SESSION_TOKEN"] = "testing"
+if TYPE_CHECKING:
+ from mypy_boto3_dynamodb.client import DynamoDBClient
+ from mypy_boto3_logs.client import CloudWatchLogsClient
+ from mypy_boto3_sns.client import SNSClient
+else:
+ DynamoDBClient = object
+ CloudWatchLogsClient = object
+ SNSClient = object
-@pytest.fixture
-def dynamodb_client(aws_credentials):
- """DDB Mock Client"""
+@fixture(autouse=True)
+def aws_credentials() -> Iterator[None]:
+ creds = {
+ "AWS_ACCESS_KEY_ID": "testing",
+ "AWS_SECRET_ACCESS_KEY": "testing",
+ "AWS_SECURITY_TOKEN": "testing",
+ "AWS_SESSION_TOKEN": "testing",
+ "AWS_DEFAULT_REGION": "us-east-1",
+ }
+ with patch.dict(environ, creds, clear=True):
+ yield
+
+
+@fixture(autouse=True)
+def app_env(aws_credentials: None) -> Iterator[AppEnv]:
+ # clear cached env for each test for isolation
+ instance_scheduler.util.app_env._app_env = None
+ env = example_app_env()
+ with patch.dict(environ, env_from_app_env(env)):
+ yield env
+
+
+@fixture(autouse=True)
+def test_cleanup() -> Iterator[None]:
+ # runs before eact test
+ yield
+ # runs after each test
+ unload_global_configuration()
+
+
+@fixture
+def moto_ec2() -> Iterator[None]:
+ with mock_ec2():
+ yield
+
+
+@fixture
+def moto_dynamodb() -> Iterator[None]:
with mock_dynamodb():
- connection = boto3.client("dynamodb", region_name="us-east-1")
- yield connection
+ yield
-@pytest.fixture
-def dynamodb_client_resource(aws_credentials):
+@fixture
+def dynamodb_client() -> Iterator[DynamoDBClient]:
"""DDB Mock Client"""
with mock_dynamodb():
- connection = boto3.resource("dynamodb", region_name="us-east-1")
+ connection = boto3.client("dynamodb", region_name="us-east-1")
yield connection
-def mock_version_module():
- module = type(sys)("version")
- module.VERSION = "1.5.0"
- return module
+@fixture
+def config_table(app_env: AppEnv, moto_dynamodb: None) -> None:
+ boto3.client("dynamodb").create_table(
+ AttributeDefinitions=[
+ {"AttributeName": "name", "AttributeType": "S"},
+ {"AttributeName": "type", "AttributeType": "S"},
+ ],
+ TableName=app_env.config_table_name,
+ KeySchema=[
+ {"AttributeName": "type", "KeyType": "HASH"},
+ {"AttributeName": "name", "KeyType": "RANGE"},
+ ],
+ BillingMode="PAY_PER_REQUEST",
+ )
+
+
+@fixture
+def moto_logs() -> Iterator[None]:
+ with mock_logs():
+ yield
+
+
+@fixture
+def mock_log_group(moto_logs: None, app_env: AppEnv) -> None:
+ logs: CloudWatchLogsClient = boto3.client("logs")
+ logs.create_log_group(logGroupName=app_env.log_group)
+
+
+@fixture
+def moto_sns() -> Iterator[None]:
+ with mock_sns():
+ yield
+
+
+@fixture
+def mock_topic(moto_sns: None, app_env: AppEnv) -> None:
+ sns: SNSClient = boto3.client("sns")
+ sns.create_topic(Name=app_env.topic_arn.split(":")[-1])
-sys.modules["version"] = mock_version_module()
+@fixture
+def moto_sts() -> Iterator[None]:
+ with mock_sts():
+ yield
diff --git a/source/app/tests/context.py b/source/app/tests/context.py
new file mode 100644
index 00000000..5eb0f866
--- /dev/null
+++ b/source/app/tests/context.py
@@ -0,0 +1,20 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from aws_lambda_powertools.utilities.typing import LambdaContext
+
+
+class MockLambdaContext(LambdaContext):
+ def __init__(self, log_group_name: str = "logGroupName") -> None:
+ self._aws_request_id = "requestId"
+ self._log_group_name = log_group_name
+ self._log_stream_name = "logStreamName"
+ self._function_name = "functionName"
+ self._memory_limit_in_mb = 128
+ self._function_version = "$LATEST"
+ self._invoked_function_arn = (
+ "arn:aws:lambda:us-east-1:123456789012:function:functionName"
+ )
+
+ @staticmethod
+ def get_remaining_time_in_millis() -> int:
+ return 2000
diff --git a/source/app/instance_scheduler/version.py b/source/app/tests/handler/__init__.py
similarity index 84%
rename from source/app/instance_scheduler/version.py
rename to source/app/tests/handler/__init__.py
index be92052a..04f8b7b7 100644
--- a/source/app/instance_scheduler/version.py
+++ b/source/app/tests/handler/__init__.py
@@ -1,5 +1,2 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-
-VERSION = "1.5.0"
diff --git a/source/app/tests/handler/conftest.py b/source/app/tests/handler/conftest.py
new file mode 100644
index 00000000..9f939435
--- /dev/null
+++ b/source/app/tests/handler/conftest.py
@@ -0,0 +1,25 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from collections.abc import Iterator
+
+from pytest import fixture
+
+
+@fixture(autouse=True)
+def moto_logs_autouse(moto_logs: None) -> Iterator[None]:
+ yield
+
+
+@fixture(autouse=True)
+def mock_log_group_autouse(mock_log_group: None) -> None:
+ """noop"""
+
+
+@fixture(autouse=True)
+def moto_sns_autouse(moto_sns: None) -> Iterator[None]:
+ yield
+
+
+@fixture(autouse=True)
+def mock_topic_autouse(mock_topic: None) -> None:
+ """noop"""
diff --git a/source/app/tests/handler/test_cfn_schedule_handler.py b/source/app/tests/handler/test_cfn_schedule_handler.py
new file mode 100644
index 00000000..f725b5d0
--- /dev/null
+++ b/source/app/tests/handler/test_cfn_schedule_handler.py
@@ -0,0 +1,165 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from datetime import time
+from unittest.mock import ANY, MagicMock, patch
+
+from instance_scheduler.configuration import get_global_configuration
+from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler.configuration.running_period import RunningPeriod
+from instance_scheduler.configuration.running_period_dict_element import (
+ RunningPeriodDictElement,
+)
+from instance_scheduler.handler.cfn_schedule import (
+ CfnScheduleHandler,
+ CfnScheduleResourceProperties,
+)
+from instance_scheduler.util.custom_resource import CustomResourceRequest
+from tests.context import MockLambdaContext
+from tests.logger import MockLogger
+from tests.test_utils.unordered_list import UnorderedList
+
+stack_arn = "arn:aws:cloudformation:us-west-2:123456789012:stack/teststack/51af3dc0-da77-11e4-872e-1234567db123"
+
+
+def new_create_request(
+ resource_properties: CfnScheduleResourceProperties,
+) -> CustomResourceRequest[CfnScheduleResourceProperties]:
+ return {
+ "RequestType": "Create",
+ "ServiceToken": "LambdaARN",
+ "ResponseURL": "url",
+ "StackId": stack_arn,
+ "RequestId": "requestId",
+ "ResourceType": "Custom::ServiceInstanceSchedule",
+ "LogicalResourceId": "CFNLogicalID",
+ "PhysicalResourceId": "PhysicalID",
+ "ResourceProperties": resource_properties,
+ }
+
+
+@patch.object(CfnScheduleHandler, "_send_response")
+def test_minimalist_cfn_schedule_creation(
+ mocked_cfn_callback: MagicMock, config_table: None
+) -> None:
+ event = new_create_request(
+ {
+ "NoStackPrefix": "True",
+ "ServiceToken": "serviceTokenARN",
+ "Periods": [{"Description": "Stop at 5pm", "EndTime": "16:59"}],
+ }
+ )
+ handler = CfnScheduleHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ expected_schedule = InstanceSchedule(
+ name="CFNLogicalID",
+ configured_in_stack=stack_arn,
+ stop_new_instances=True,
+ use_metrics=False,
+ description="",
+ periods=[
+ RunningPeriodDictElement(
+ period=RunningPeriod(name=ANY, endtime=time(16, 59, 0)),
+ instancetype=None,
+ )
+ ],
+ )
+
+ assert handler.response["Status"] == "SUCCESS", handler.response[
+ "Reason"
+ ] # todo: appears to return timeout even for exceptions within code? (6/30/23)
+ # -- action: improve error reporting
+ global_config = get_global_configuration(MockLogger())
+ assert len(global_config.schedules) == 1
+ assert "CFNLogicalID" in global_config.schedules
+ assert global_config.schedules["CFNLogicalID"] == expected_schedule
+
+
+@patch.object(CfnScheduleHandler, "_send_response")
+def test_cfn_schedule_with_all_parameters(
+ mocked_cfn_callback: MagicMock, config_table: None
+) -> None:
+ # untested properties:
+ # "Overwrite"
+ # "OverrideStatus"
+ # "Metrics"
+
+ event = new_create_request(
+ {
+ "ServiceToken": "ServiceTokenARN",
+ "NoStackPrefix": "True",
+ "Name": "schedule_name",
+ "Description": "template with all values",
+ "Timezone": "America/New_York",
+ "Enforced": "True",
+ "Hibernate": "True",
+ "RetainRunning": "True",
+ "StopNewInstances": "True",
+ "UseMaintenanceWindow": "True",
+ "SsmMaintenanceWindow": "my_window_name",
+ "Periods": [
+ {
+ "Description": "run from 9-5 on the first 3 days of March",
+ "BeginTime": "9:00",
+ "EndTime": "17:00",
+ "InstanceType": "t2.micro",
+ "MonthDays": "1-3",
+ "Months": "3",
+ },
+ {
+ "Description": "run from 2pm-5pm on the weekends",
+ "BeginTime": "14:00",
+ "EndTime": "17:00",
+ "InstanceType": "t2.micro",
+ "WeekDays": "Sat-Sun",
+ },
+ ],
+ }
+ )
+
+ expected_schedule = InstanceSchedule(
+ name="schedule_name",
+ description="template with all values",
+ timezone="America/New_York",
+ configured_in_stack=stack_arn,
+ enforced=True,
+ hibernate=True,
+ retain_running=True,
+ stop_new_instances=True,
+ use_maintenance_window=True,
+ ssm_maintenance_window="my_window_name",
+ use_metrics=False,
+ periods=UnorderedList(
+ [
+ RunningPeriodDictElement(
+ period=RunningPeriod(
+ name=ANY,
+ begintime=time(9, 0, 0),
+ endtime=time(17, 0, 0),
+ monthdays={1, 2, 3},
+ months={3},
+ ),
+ instancetype="t2.micro",
+ ),
+ RunningPeriodDictElement(
+ period=RunningPeriod(
+ name=ANY,
+ begintime=time(14, 0, 0),
+ endtime=time(17, 0, 0),
+ weekdays={5, 6},
+ ),
+ instancetype="t2.micro",
+ ),
+ ]
+ ),
+ )
+
+ handler = CfnScheduleHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ assert handler.response["Status"] == "SUCCESS", handler.response["Reason"]
+ global_config = get_global_configuration(MockLogger())
+ assert len(global_config.schedules) == 1
+ assert "schedule_name" in global_config.schedules
+ saved_schedule = global_config.schedules["schedule_name"]
+ assert saved_schedule == expected_schedule
diff --git a/source/app/tests/handler/test_cli_handler.py b/source/app/tests/handler/test_cli_handler.py
new file mode 100644
index 00000000..cc05dd63
--- /dev/null
+++ b/source/app/tests/handler/test_cli_handler.py
@@ -0,0 +1,582 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from datetime import date
+from typing import Any, Optional, Sequence
+
+from instance_scheduler.handler.cli import CliHandler
+from instance_scheduler.util.app_env import AppEnv
+from instance_scheduler.util.dynamodb_utils import DynamoDBUtils
+from tests.context import MockLambdaContext
+from tests.test_utils.unordered_list import UnorderedList
+
+
+def test_is_handling_request() -> None:
+ assert CliHandler.is_handling_request(
+ {"source": "scheduler.cli", "action": "something"}
+ )
+
+ assert not CliHandler.is_handling_request(
+ {"source": "anything.else", "action": "another_thing"}
+ )
+
+
+def test_create_schedule_throws_error_when_period_not_found(config_table: None) -> None:
+ result = create_schedule_with_cli(periods=["office-hours"])
+ assert result == {"Error": "error: not found: period office-hours does not exist"}
+
+
+def test_create_schedule_with_2_periods(config_table: None, app_env: AppEnv) -> None:
+ create_period_with_cli(name="period1")
+ create_period_with_cli(name="period2")
+
+ result = create_schedule_with_cli(
+ periods=["period1", "period2"], name="cli-schedule"
+ )
+
+ assert result == {
+ "Schedule": {
+ "Name": "cli-schedule",
+ "Periods": UnorderedList(["period1", "period2"]),
+ "StopNewInstances": True,
+ "UseMaintenanceWindow": False,
+ "RetainRunning": False,
+ "Enforced": False,
+ "Hibernate": False,
+ "UseMetrics": False,
+ "Type": "schedule",
+ }
+ }
+
+ created_schedule = get_schedule_from_dynamo("cli-schedule", app_env)
+ assert created_schedule == {
+ "type": "schedule",
+ "name": "cli-schedule",
+ "periods": {"period1", "period2"},
+ "stop_new_instances": True,
+ "use_maintenance_window": False,
+ "retain_running": False,
+ "enforced": False,
+ "hibernate": False,
+ "use_metrics": False,
+ }
+
+
+def test_create_schedule_throws_error_when_schedule_already_exists(
+ config_table: None,
+) -> None:
+ create_period_with_cli(name="period1")
+ create_schedule_with_cli(name="cli-schedule", periods=["period1"])
+ result = create_schedule_with_cli(name="cli-schedule", periods=["period1"])
+
+ assert result == {"Error": "error: schedule cli-schedule already exists"}
+
+
+def test_delete_existing_schedule(config_table: None, app_env: AppEnv) -> None:
+ create_period_with_cli(name="period1")
+ create_period_with_cli(name="period2")
+ create_schedule_with_cli(periods=["period1", "period2"], name="cli-schedule")
+
+ assert get_schedule_from_dynamo("cli-schedule", app_env) is not None
+ result = delete_schedule_with_cli("cli-schedule")
+ assert result == {"Schedule": "cli-schedule"}
+ assert get_schedule_from_dynamo("cli-schedule", app_env) is None
+
+
+def test_delete_nonexisting_schedule_returns_error(config_table: None) -> None:
+ result = delete_period_with_cli("cli-schedule")
+ assert result == {"Error": "not found: period cli-schedule does not exist"}
+
+
+def test_create_basic_period(config_table: None, app_env: AppEnv) -> None:
+ result = create_period_with_cli(
+ name="cli-period", begintime="10:00", endtime="20:00"
+ )
+
+ assert result == {
+ "Period": {
+ "Begintime": "10:00",
+ "Endtime": "20:00",
+ "Name": "cli-period",
+ "Type": "period",
+ }
+ }
+
+ created_period = get_period_from_dynamo(name="cli-period", app_env=app_env)
+ assert created_period == {
+ "type": "period",
+ "name": "cli-period",
+ "begintime": "10:00",
+ "endtime": "20:00",
+ }
+
+
+def test_create_period_throws_error_when_period_already_exists(
+ config_table: None,
+) -> None:
+ create_period_with_cli(name="cli-period")
+ result = create_period_with_cli(name="cli-period")
+
+ assert result == {"Error": "error: period cli-period already exists"}
+
+
+def test_delete_existing_period(config_table: None, app_env: AppEnv) -> None:
+ create_period_with_cli(name="cli-period")
+
+ assert get_period_from_dynamo("cli-period", app_env) is not None
+ result = delete_period_with_cli("cli-period")
+ assert result == {"Period": "cli-period"}
+ assert get_period_from_dynamo("cli-period", app_env) is None
+
+
+def test_delete_nonexisting_period_returns_error(config_table: None) -> None:
+ result = delete_period_with_cli("cli-period")
+ assert result == {"Error": "not found: period cli-period does not exist"}
+
+
+def test_describe_all_periods_is_empty_when_no_periods_created(
+ config_table: None,
+) -> None:
+ result = describe_periods()
+ assert result == {"Periods": []}
+
+
+def test_describe_all_periods_returns_created_periods(config_table: None) -> None:
+ create_period_with_cli("period1", begintime="5:00", endtime="10:00"),
+ create_period_with_cli("period2", begintime="12:00", endtime="14:00")
+ result = describe_periods()
+ assert result == {
+ "Periods": UnorderedList(
+ [
+ {
+ "Type": "period",
+ "Name": "period1",
+ "Begintime": "05:00",
+ "Endtime": "10:00",
+ },
+ {
+ "Type": "period",
+ "Name": "period2",
+ "Begintime": "12:00",
+ "Endtime": "14:00",
+ },
+ ]
+ )
+ }
+
+
+def test_describe_specific_period_returns_expected_period(config_table: None) -> None:
+ create_period_with_cli("period1", begintime="5:00", endtime="10:00"),
+ create_period_with_cli("period2", begintime="12:00", endtime="14:00")
+ result = describe_periods("period1")
+ assert result == {
+ "Periods": UnorderedList(
+ [
+ {
+ "Type": "period",
+ "Name": "period1",
+ "Begintime": "05:00",
+ "Endtime": "10:00",
+ },
+ ]
+ )
+ }
+
+
+def test_describe_specific_period_returns_error_when_not_exists(
+ config_table: None,
+) -> None:
+ create_period_with_cli("period1", begintime="5:00", endtime="10:00"),
+ create_period_with_cli("period2", begintime="12:00", endtime="14:00")
+ result = describe_periods("period3")
+ assert result == {"Error": "not found: period period3 does not exist"}
+
+
+def test_describe_all_schedules_is_empty_when_no_schedules_created(
+ config_table: None,
+) -> None:
+ result = describe_schedules()
+ assert result == {"Schedules": []}
+
+
+def test_describe_all_schedules_returns_created_schedules(config_table: None) -> None:
+ create_period_with_cli("period1", begintime="5:00", endtime="10:00"),
+ create_period_with_cli("period2", begintime="12:00", endtime="14:00")
+ create_schedule_with_cli(
+ periods=["period1"], name="schedule1", stop_new_instances=False
+ )
+ create_schedule_with_cli(periods=["period2"], name="schedule2", retain_running=True)
+
+ result = describe_schedules()
+ assert result == {
+ "Schedules": UnorderedList(
+ [
+ {
+ "Type": "schedule",
+ "Name": "schedule1",
+ "Periods": ["period1"],
+ "StopNewInstances": False,
+ "UseMaintenanceWindow": False,
+ "RetainRunning": False,
+ "Enforced": False,
+ "Hibernate": False,
+ "UseMetrics": False,
+ },
+ {
+ "Type": "schedule",
+ "Name": "schedule2",
+ "Periods": ["period2"],
+ "StopNewInstances": True,
+ "UseMaintenanceWindow": False,
+ "RetainRunning": True,
+ "Enforced": False,
+ "Hibernate": False,
+ "UseMetrics": False,
+ },
+ ]
+ )
+ }
+
+
+def test_describe_specific_schedule_returns_expected_schedule(
+ config_table: None,
+) -> None:
+ create_period_with_cli("period1", begintime="5:00", endtime="10:00"),
+ create_period_with_cli("period2", begintime="12:00", endtime="14:00")
+ create_schedule_with_cli(
+ periods=["period1"],
+ name="schedule1",
+ use_maintenance_window=True,
+ ssm_maintenance_window="window",
+ )
+ create_schedule_with_cli(periods=["period2"], name="schedule2", enforced=True)
+
+ result = describe_schedules("schedule1")
+ assert result == {
+ "Schedules": [
+ {
+ "Type": "schedule",
+ "Name": "schedule1",
+ "Periods": ["period1"],
+ "StopNewInstances": True,
+ "UseMaintenanceWindow": True,
+ "SsmMaintenanceWindow": "window",
+ "RetainRunning": False,
+ "Enforced": False,
+ "Hibernate": False,
+ "UseMetrics": False,
+ },
+ ]
+ }
+
+
+def test_describe_specific_schedule_returns_error_when_not_exists(
+ config_table: None,
+) -> None:
+ create_period_with_cli("period1", begintime="5:00", endtime="10:00"),
+ create_period_with_cli("period2", begintime="12:00", endtime="14:00")
+ create_schedule_with_cli(
+ periods=["period1"],
+ name="schedule1",
+ use_maintenance_window=True,
+ ssm_maintenance_window="window",
+ )
+ create_schedule_with_cli(periods=["period2"], name="schedule2", enforced=True)
+
+ result = describe_schedules("schedule3")
+ assert result == {"Error": "not found: schedule schedule3 does not exist"}
+
+
+def test_describe_schedule_usage(config_table: None) -> None:
+ create_period_with_cli("cli-period", begintime="9:00", endtime="17:00"),
+ create_schedule_with_cli(periods=["cli-period"], name="cli-schedule")
+ result = describe_schedule_usage(
+ "cli-schedule", startdate=date(2023, 7, 20), enddate=date(2023, 7, 21)
+ )
+ assert result == {
+ "Schedule": "cli-schedule",
+ "Usage": {
+ "2023-07-20": {
+ "BillingHours": 8,
+ "BillingSeconds": 28800,
+ "RunningPeriods": {
+ "Cli-period": {
+ "Begin": "07/20/23 09:00:00",
+ "BillingHours": 8,
+ "BillingSeconds": 28800,
+ "End": "07/20/23 17:00:00",
+ }
+ },
+ },
+ "2023-07-21": {
+ "BillingHours": 8,
+ "BillingSeconds": 28800,
+ "RunningPeriods": {
+ "Cli-period": {
+ "Begin": "07/21/23 09:00:00",
+ "BillingHours": 8,
+ "BillingSeconds": 28800,
+ "End": "07/21/23 17:00:00",
+ }
+ },
+ },
+ },
+ }
+
+
+def test_update_period(config_table: None, app_env: AppEnv) -> None:
+ create_period_with_cli("cli-period", begintime="2:00", endtime="4:00")
+ result = update_period_with_cli("cli-period", begintime="12:00", endtime="15:00")
+
+ assert result == {
+ "Period": {
+ "Begintime": "12:00",
+ "Endtime": "15:00",
+ "Name": "cli-period",
+ "Type": "period",
+ }
+ }
+
+ updated_period = get_period_from_dynamo("cli-period", app_env)
+ assert updated_period == {
+ "type": "period",
+ "name": "cli-period",
+ "begintime": "12:00",
+ "endtime": "15:00",
+ }
+
+
+def test_update_period_returns_error_when_period_does_not_exist(
+ config_table: None,
+) -> None:
+ result = update_period_with_cli("cli-period", begintime="12:00", endtime="15:00")
+
+ assert result == {"Error": "not found: period cli-period does not exist"}
+
+
+def test_update_schedule(config_table: None, app_env: AppEnv) -> None:
+ create_period_with_cli("period1")
+ create_period_with_cli("period2")
+ create_schedule_with_cli(
+ periods=["period1"], name="cli-schedule", retain_running=True
+ )
+
+ result = update_schedule_with_cli(
+ name="cli-schedule",
+ periods=["period1", "period2"],
+ retain_running=False,
+ enforced=True,
+ )
+
+ assert result == {
+ "Schedule": {
+ "Name": "cli-schedule",
+ "Periods": UnorderedList(["period1", "period2"]),
+ "StopNewInstances": True,
+ "UseMaintenanceWindow": False,
+ "RetainRunning": False,
+ "Enforced": True,
+ "Hibernate": False,
+ "UseMetrics": False,
+ "Type": "schedule",
+ }
+ }
+
+ updated_schedule = get_schedule_from_dynamo("cli-schedule", app_env)
+ assert updated_schedule == {
+ "type": "schedule",
+ "name": "cli-schedule",
+ "periods": {"period1", "period2"},
+ "stop_new_instances": True,
+ "use_maintenance_window": False,
+ "retain_running": False,
+ "enforced": True,
+ "hibernate": False,
+ "use_metrics": False,
+ }
+
+
+def test_update_schedule_returns_error_when_schedule_does_not_exist(
+ config_table: None,
+) -> None:
+ create_period_with_cli("period1")
+ result = update_schedule_with_cli(name="cli-schedule", periods=["period1"])
+
+ assert result == {"Error": "not found: schedule cli-schedule does not exist"}
+
+
+def test_update_schedule_returns_error_when_period_does_not_exist(
+ config_table: None,
+) -> None:
+ result = update_schedule_with_cli(name="cli-schedule", periods=["period1"])
+
+ assert result == {"Error": "error: not found: period period1 does not exist"}
+
+
+# ------------------------------Begin Helpers------------------------------ #
+
+
+def create_period_with_cli(
+ name: str = "cli-period", begintime: str = "10:00", endtime: str = "20:00"
+) -> Any:
+ event = {
+ "source": "scheduler.cli",
+ "action": "create-period",
+ "parameters": {"name": name, "begintime": begintime, "endtime": endtime},
+ }
+
+ handler = CliHandler(event, MockLambdaContext())
+ return handler.handle_request()
+
+
+def update_period_with_cli(
+ name: str = "cli-period", begintime: str = "10:00", endtime: str = "20:00"
+) -> Any:
+ event = {
+ "source": "scheduler.cli",
+ "action": "update-period",
+ "parameters": {"name": name, "begintime": begintime, "endtime": endtime},
+ }
+
+ handler = CliHandler(event, MockLambdaContext())
+ return handler.handle_request()
+
+
+def delete_period_with_cli(name: str) -> Any:
+ event = {
+ "source": "scheduler.cli",
+ "action": "delete-period",
+ "parameters": {"name": name},
+ }
+ handler = CliHandler(event, MockLambdaContext())
+ return handler.handle_request()
+
+
+def create_schedule_with_cli(
+ periods: Sequence[str],
+ name: str = "cli-schedule",
+ stop_new_instances: bool = True,
+ use_maintenance_window: bool = False,
+ retain_running: bool = False,
+ enforced: bool = False,
+ hibernate: bool = False,
+ use_metrics: bool = False,
+ ssm_maintenance_window: Optional[str] = None,
+) -> Any:
+ event: dict[str, Any] = {
+ "source": "scheduler.cli",
+ "action": "create-schedule",
+ "parameters": {
+ "name": name,
+ "periods": ",".join(periods),
+ "stop_new_instances": stop_new_instances,
+ "use_maintenance_window": use_maintenance_window,
+ "retain_running": retain_running,
+ "enforced": enforced,
+ "hibernate": hibernate,
+ "use-metrics": use_metrics,
+ },
+ }
+
+ if ssm_maintenance_window:
+ event["parameters"]["ssm_maintenance_window"] = ssm_maintenance_window
+
+ handler = CliHandler(event, MockLambdaContext())
+ return handler.handle_request()
+
+
+def update_schedule_with_cli(
+ periods: Sequence[str],
+ name: str = "cli-schedule",
+ stop_new_instances: bool = True,
+ use_maintenance_window: bool = False,
+ retain_running: bool = False,
+ enforced: bool = False,
+ hibernate: bool = False,
+ use_metrics: bool = False,
+ ssm_maintenance_window: Optional[str] = None,
+) -> Any:
+ event: dict[str, Any] = {
+ "source": "scheduler.cli",
+ "action": "update-schedule",
+ "parameters": {
+ "name": name,
+ "periods": ",".join(periods),
+ "stop_new_instances": stop_new_instances,
+ "use_maintenance_window": use_maintenance_window,
+ "retain_running": retain_running,
+ "enforced": enforced,
+ "hibernate": hibernate,
+ "use-metrics": use_metrics,
+ },
+ }
+
+ if ssm_maintenance_window:
+ event["parameters"]["ssm_maintenance_window"] = ssm_maintenance_window
+
+ handler = CliHandler(event, MockLambdaContext())
+ return handler.handle_request()
+
+
+def delete_schedule_with_cli(name: str) -> Any:
+ event = {
+ "source": "scheduler.cli",
+ "action": "delete-schedule",
+ "parameters": {"name": name},
+ }
+ handler = CliHandler(event, MockLambdaContext())
+ return handler.handle_request()
+
+
+def describe_periods(name: Optional[str] = None) -> Any:
+ event: dict[str, Any] = {
+ "source": "scheduler.cli",
+ "action": "describe-periods",
+ "parameters": {},
+ }
+
+ if name:
+ event["parameters"]["name"] = name
+
+ handler = CliHandler(event, MockLambdaContext())
+ return handler.handle_request()
+
+
+def describe_schedules(name: Optional[str] = None) -> Any:
+ event: dict[str, Any] = {
+ "source": "scheduler.cli",
+ "action": "describe-schedules",
+ "parameters": {},
+ }
+
+ if name:
+ event["parameters"]["name"] = name
+
+ handler = CliHandler(event, MockLambdaContext())
+ return handler.handle_request()
+
+
+def describe_schedule_usage(name: str, startdate: date, enddate: date) -> Any:
+ event = {
+ "source": "scheduler.cli",
+ "action": "describe-schedule-usage",
+ "parameters": {
+ "name": name,
+ "startdate": startdate.strftime("%Y%m%d"),
+ "enddate": enddate.strftime("%Y%m%d"),
+ },
+ }
+
+ handler = CliHandler(event, MockLambdaContext())
+ return handler.handle_request()
+
+
+def get_period_from_dynamo(name: str, app_env: AppEnv) -> Any:
+ table = DynamoDBUtils.get_dynamodb_table_resource_ref(app_env.config_table_name)
+ result = table.get_item(Key={"type": "period", "name": name}, ConsistentRead=True)
+ return result.get("Item")
+
+
+def get_schedule_from_dynamo(name: str, app_env: AppEnv) -> Any:
+ table = DynamoDBUtils.get_dynamodb_table_resource_ref(app_env.config_table_name)
+ result = table.get_item(Key={"type": "schedule", "name": name}, ConsistentRead=True)
+ return result.get("Item")
diff --git a/source/app/tests/handler/test_eventbus_request_handler.py b/source/app/tests/handler/test_eventbus_request_handler.py
new file mode 100644
index 00000000..ffe2f9bc
--- /dev/null
+++ b/source/app/tests/handler/test_eventbus_request_handler.py
@@ -0,0 +1,62 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from aws_lambda_powertools.utilities.typing import LambdaContext
+
+from instance_scheduler.handler.spoke_registration import SpokeRegistrationHandler
+from instance_scheduler.util.app_env import AppEnv
+from instance_scheduler.util.dynamodb_utils import DynamoDBUtils
+
+
+def test_handler(app_env: AppEnv, config_table: None) -> None:
+ create_event = {
+ "version": "0",
+ "id": "c4556ddf-88ad-1b22-e482-19f2d72eb7e3",
+ "detail-type": "Parameter Store Change",
+ "source": "aws.ssm",
+ "account": "111111111111",
+ "time": "2021-08-19T06:26:38Z",
+ "region": "us-east-1",
+ "resources": [
+ "arn:aws:ssm:us-east-1:111111111111:parameter/scheduler/do-not-delete-manually/static"
+ ],
+ "detail": {
+ "name": "/scheduler/do-not-delete-manually/static",
+ "type": "String",
+ "operation": "Create",
+ },
+ }
+ dynamodb_table = DynamoDBUtils.get_dynamodb_table_resource_ref(
+ app_env.config_table_name
+ )
+ dynamodb_table.put_item(
+ Item={"type": "config", "name": "scheduler", "namespace": "static"}
+ )
+ handler = SpokeRegistrationHandler(create_event, LambdaContext())
+ response: bool | str = handler.is_handling_request(create_event)
+ assert response is True
+
+ response = handler.handle_request()
+ assert response == "Exiting event bus request handler"
+ delete_event = {
+ "version": "0",
+ "id": "c4556ddf-88ad-1b22-e482-19f2d72eb7e3",
+ "detail-type": "Parameter Store Change",
+ "source": "aws.ssm",
+ "account": "111111111111",
+ "time": "2021-08-19T06:26:38Z",
+ "region": "us-east-1",
+ "resources": [
+ "arn:aws:ssm:us-east-1:111111111111:parameter/scheduler/do-not-delete-manually/static"
+ ],
+ "detail": {
+ "name": "/scheduler/do-not-delete-manually/static",
+ "type": "String",
+ "operation": "Delete",
+ },
+ }
+ handler = SpokeRegistrationHandler(delete_event, LambdaContext())
+ response = handler.is_handling_request(delete_event)
+ assert response is True
+
+ response = handler.handle_request()
+ assert response == "Exiting event bus request handler"
diff --git a/source/app/tests/handler/test_scheduler_setup_handler.py b/source/app/tests/handler/test_scheduler_setup_handler.py
new file mode 100644
index 00000000..0c17e9f1
--- /dev/null
+++ b/source/app/tests/handler/test_scheduler_setup_handler.py
@@ -0,0 +1,183 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from os import environ
+
+import boto3
+
+from instance_scheduler.handler.config_resource import SchedulerSetupHandler
+from instance_scheduler.util.app_env import AppEnv
+from tests.context import MockLambdaContext
+
+
+def test_a_valid_org_id_pattern() -> None:
+ handler = SchedulerSetupHandler(
+ {"ResourceProperties": {"stack_version": "test"}}, MockLambdaContext()
+ )
+ response = handler.get_valid_org_id("o-x1mhq1lvsr")
+ assert response
+
+
+def test_an_invalid_org_id_pattern() -> None:
+ handler = SchedulerSetupHandler(
+ {"ResourceProperties": {"stack_version": "test"}}, MockLambdaContext()
+ )
+ response = handler.get_valid_org_id("111111111111,222222222222")
+ assert response is None
+
+
+def test_create_request(config_table: None) -> None:
+ """Happy path no errors"""
+ handler = SchedulerSetupHandler(
+ {
+ "ResourceProperties": {
+ "stack_version": "test",
+ "remote_account_ids": ["111111111111"],
+ "scheduled_services": ["ec2"],
+ "regions": ["us-east-1"],
+ }
+ },
+ MockLambdaContext(),
+ )
+ assert handler._create_request() is True
+
+
+def test_update_request(config_table: None) -> None:
+ """Happy path no errors"""
+ handler = SchedulerSetupHandler(
+ {
+ "ResourceProperties": {
+ "stack_version": "test",
+ "remote_account_ids": ["111111111111"],
+ "scheduled_services": ["ec2"],
+ "regions": ["us-east-1"],
+ }
+ },
+ MockLambdaContext(),
+ )
+ assert handler._update_request() is True
+
+
+def test_regions() -> None:
+ regions = ["us-east-1", "us-west-2"]
+ handler = SchedulerSetupHandler(
+ {"ResourceProperties": {"stack_version": "test", "regions": regions}},
+ MockLambdaContext(),
+ )
+ assert handler.regions == set(regions)
+
+
+def test_regions_empty() -> None:
+ handler = SchedulerSetupHandler(
+ {"ResourceProperties": {"stack_version": "test", "regions": []}},
+ MockLambdaContext(),
+ )
+ assert handler.regions == [environ["AWS_DEFAULT_REGION"]]
+
+
+def test_regions_empty_strings() -> None:
+ handler = SchedulerSetupHandler(
+ {"ResourceProperties": {"stack_version": "test", "regions": ["", ""]}},
+ MockLambdaContext(),
+ )
+ assert handler.regions == [environ["AWS_DEFAULT_REGION"]]
+
+
+def test_remote_account_ids() -> None:
+ accounts = ["111111111111", "222222222222"]
+ handler = SchedulerSetupHandler(
+ {
+ "ResourceProperties": {
+ "stack_version": "test",
+ "remote_account_ids": accounts,
+ }
+ },
+ MockLambdaContext(),
+ )
+ assert handler.remote_account_ids == set(accounts)
+
+
+def test_remote_account_ids_empty() -> None:
+ handler = SchedulerSetupHandler(
+ {"ResourceProperties": {"stack_version": "test", "remote_account_ids": []}},
+ MockLambdaContext(),
+ )
+ assert not handler.remote_account_ids
+
+
+def test_remote_account_ids_empty_strings() -> None:
+ handler = SchedulerSetupHandler(
+ {
+ "ResourceProperties": {
+ "stack_version": "test",
+ "remote_account_ids": ["", ""],
+ }
+ },
+ MockLambdaContext(),
+ )
+ assert not handler.remote_account_ids
+
+
+def test_scheduled_services() -> None:
+ services = ["ec2", "rds"]
+ handler = SchedulerSetupHandler(
+ {
+ "ResourceProperties": {
+ "stack_version": "test",
+ "scheduled_services": services,
+ }
+ },
+ MockLambdaContext(),
+ )
+ assert handler.scheduled_services == set(services)
+
+
+def test_scheduled_services_empty() -> None:
+ handler = SchedulerSetupHandler(
+ {"ResourceProperties": {"stack_version": "test", "scheduled_services": []}},
+ MockLambdaContext(),
+ )
+ assert not handler.scheduled_services
+
+
+def test_scheduled_services_empty_strings() -> None:
+ handler = SchedulerSetupHandler(
+ {
+ "ResourceProperties": {
+ "stack_version": "test",
+ "scheduled_services": ["", ""],
+ }
+ },
+ MockLambdaContext(),
+ )
+ assert not handler.scheduled_services
+
+
+def test_set_lambda_logs_retention_period(app_env: AppEnv) -> None:
+ """With no period, expect set to default"""
+ log_group = app_env.log_group
+ handler = SchedulerSetupHandler(
+ {"ResourceProperties": {"stack_version": "test"}}, MockLambdaContext(log_group)
+ )
+ handler.set_lambda_logs_retention_period()
+ response = boto3.client("logs").describe_log_groups(logGroupNamePrefix=log_group)
+ assert response["logGroups"][0]["logGroupName"] == log_group
+ assert response["logGroups"][0]["retentionInDays"] == 30
+
+
+def test_set_lambda_logs_retention_period_custom_retention(app_env: AppEnv) -> None:
+ """With custom period, expect set to desired"""
+ log_group = app_env.log_group
+ retention_period = 90
+ handler = SchedulerSetupHandler(
+ {
+ "ResourceProperties": {
+ "stack_version": "test",
+ "log_retention_days": retention_period,
+ }
+ },
+ MockLambdaContext(log_group),
+ )
+ handler.set_lambda_logs_retention_period()
+ response = boto3.client("logs").describe_log_groups(logGroupNamePrefix=log_group)
+ assert response["logGroups"][0]["logGroupName"] == log_group
+ assert response["logGroups"][0]["retentionInDays"] == retention_period
diff --git a/source/app/tests/handler/test_scheduling_orchestration_handler.py b/source/app/tests/handler/test_scheduling_orchestration_handler.py
new file mode 100644
index 00000000..b1516fc9
--- /dev/null
+++ b/source/app/tests/handler/test_scheduling_orchestration_handler.py
@@ -0,0 +1,317 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import datetime
+from typing import Any
+from unittest.mock import MagicMock, patch
+
+from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler.configuration.running_period import RunningPeriod
+from instance_scheduler.configuration.running_period_dict_element import (
+ RunningPeriodDictElement,
+)
+from instance_scheduler.configuration.scheduler_config import GlobalConfig
+from instance_scheduler.handler.scheduling_orchestrator import (
+ OrchestrationRequest,
+ SchedulingOrchestratorHandler,
+)
+from tests.context import MockLambdaContext
+
+
+def get_scheduler_conf_defaults() -> dict[str, Any]:
+ return {
+ "scheduled_services": ["ec2"],
+ "schedule_clusters": False,
+ "tag_name": "Schedule",
+ "regions": [],
+ "default_timezone": "UTC",
+ "schedules": {
+ "test-schedule": InstanceSchedule(
+ name="test-schedule",
+ periods=[
+ RunningPeriodDictElement(
+ period=RunningPeriod(
+ name="test-period",
+ begintime=datetime.time(10, 0, 0),
+ endtime=datetime.time(20, 0, 0),
+ )
+ )
+ ],
+ )
+ },
+ "trace": "False",
+ "enable_ssm_maintenance_windows": False,
+ "use_metrics": "False",
+ "schedule_lambda_account": True,
+ "create_rds_snapshot": False,
+ "started_tags": "",
+ "stopped_tags": "",
+ "scheduler_role_name": "Scheduler-Role",
+ "namespace": "dev",
+ "organization_id": "",
+ "aws_partition": "aws",
+ "remote_account_ids": [],
+ }
+
+
+mockEvent: OrchestrationRequest = {"scheduled_action": "run_orchestrator"}
+
+
+@patch.object(SchedulingOrchestratorHandler, "_run_scheduling_lambda")
+def test_no_region_provided_uses_local_region(
+ run_scheduling_lambda_func: MagicMock,
+) -> None:
+ conf = get_scheduler_conf_defaults()
+ conf["scheduled_services"] = ["ec2"]
+ conf["regions"] = []
+
+ with patch.object(
+ SchedulingOrchestratorHandler, "configuration", GlobalConfig(**conf)
+ ):
+ cloudwatch_handler = SchedulingOrchestratorHandler(
+ event=mockEvent, context=MockLambdaContext()
+ )
+ cloudwatch_handler.handle_request()
+
+ assert run_scheduling_lambda_func.call_count == 1
+
+ scheduling_context = run_scheduling_lambda_func.call_args.args[0]
+ assert scheduling_context.schedule_lambda_account is True
+ assert scheduling_context.service == "ec2"
+
+ assert scheduling_context.region == "us-east-1"
+
+
+@patch.object(SchedulingOrchestratorHandler, "_run_scheduling_lambda")
+def test_no_service_provided_does_not_run_any_lambdas(
+ run_scheduling_lambda_func: MagicMock,
+) -> None:
+ conf = get_scheduler_conf_defaults()
+ conf["scheduled_services"] = []
+ conf["regions"] = ["us-east-1"]
+
+ with patch.object(
+ SchedulingOrchestratorHandler, "configuration", GlobalConfig(**conf)
+ ):
+ cloudwatch_handler = SchedulingOrchestratorHandler(
+ event=mockEvent, context=MockLambdaContext()
+ )
+ cloudwatch_handler.handle_request()
+
+ assert run_scheduling_lambda_func.call_count == 0
+
+
+@patch.object(SchedulingOrchestratorHandler, "_run_scheduling_lambda")
+def test_remote_account_only_does_not_schedule_locally(
+ run_scheduling_lambda_func: MagicMock,
+) -> None:
+ conf = get_scheduler_conf_defaults()
+ conf["scheduled_services"] = ["ec2"]
+ conf["regions"] = ["us-east-1"]
+ conf["remote_account_ids"] = ["222233334444"]
+ conf["schedule_lambda_account"] = False
+
+ with patch.object(
+ SchedulingOrchestratorHandler, "configuration", GlobalConfig(**conf)
+ ):
+ cloudwatch_handler = SchedulingOrchestratorHandler(
+ event=mockEvent, context=MockLambdaContext()
+ )
+ cloudwatch_handler.handle_request()
+
+ assert run_scheduling_lambda_func.call_count == 1
+
+ scheduling_context = run_scheduling_lambda_func.call_args.args[0]
+ assert scheduling_context.schedule_lambda_account is False
+ assert scheduling_context.service == "ec2"
+ assert scheduling_context.account_id == "222233334444"
+ assert scheduling_context.region == "us-east-1"
+
+
+@patch.object(SchedulingOrchestratorHandler, "_run_scheduling_lambda")
+def test_1region_1service_calls_scheduler_x1(
+ run_scheduling_lambda_func: MagicMock,
+) -> None:
+ conf = get_scheduler_conf_defaults()
+ conf["scheduled_services"] = ["ec2"]
+ conf["regions"] = ["us-east-1"]
+
+ with patch.object(
+ SchedulingOrchestratorHandler, "configuration", GlobalConfig(**conf)
+ ):
+ cloudwatch_handler = SchedulingOrchestratorHandler(
+ event=mockEvent, context=MockLambdaContext()
+ )
+ cloudwatch_handler.handle_request()
+
+ assert run_scheduling_lambda_func.call_count == 1
+
+ scheduling_context = run_scheduling_lambda_func.call_args.args[0]
+ assert scheduling_context.region == "us-east-1"
+ assert scheduling_context.service == "ec2"
+
+
+@patch.object(SchedulingOrchestratorHandler, "_run_scheduling_lambda")
+def test_2region_1service_calls_scheduler_x2(
+ run_scheduling_lambda_func: MagicMock,
+) -> None:
+ conf = get_scheduler_conf_defaults()
+ conf["scheduled_services"] = ["ec2"]
+ conf["regions"] = ["us-east-1", "us-east-2"]
+
+ with patch.object(
+ SchedulingOrchestratorHandler, "configuration", GlobalConfig(**conf)
+ ):
+ cloudwatch_handler = SchedulingOrchestratorHandler(
+ event=mockEvent, context=MockLambdaContext()
+ )
+ cloudwatch_handler.handle_request()
+
+ assert run_scheduling_lambda_func.call_count == 2
+
+ # first call
+ scheduling_context = run_scheduling_lambda_func.call_args_list[0].args[0]
+ assert scheduling_context.region == "us-east-1"
+ assert scheduling_context.service == "ec2"
+
+ # second call
+ scheduling_context = run_scheduling_lambda_func.call_args_list[1].args[0]
+ assert scheduling_context.region == "us-east-2"
+ assert scheduling_context.service == "ec2"
+
+
+@patch.object(SchedulingOrchestratorHandler, "_run_scheduling_lambda")
+def test_2accounts_1region_1service_nolocal_calls_scheduler_twice(
+ run_scheduling_lambda_func: MagicMock,
+) -> None:
+ conf = get_scheduler_conf_defaults()
+ conf["scheduled_services"] = ["ec2"]
+ conf["regions"] = ["us-east-1"]
+ conf["schedule_lambda_account"] = False
+ conf["remote_account_ids"] = ["222233334444", "333344445555"]
+
+ # awkward behavior:
+ # providing local account (as defined in mockEvent) as one of the remote accounts
+ # causes scheduling in local-mode (remote id removed, schedule_lambda_account = true)
+
+ with patch.object(
+ SchedulingOrchestratorHandler, "configuration", GlobalConfig(**conf)
+ ):
+ cloudwatch_handler = SchedulingOrchestratorHandler(
+ event=mockEvent, context=MockLambdaContext()
+ )
+ cloudwatch_handler.handle_request()
+
+ assert run_scheduling_lambda_func.call_count == 2
+
+ # first call
+ scheduling_context = run_scheduling_lambda_func.call_args_list[0].args[0]
+ assert scheduling_context.region == "us-east-1"
+ assert scheduling_context.service == "ec2"
+ assert scheduling_context.account_id == "222233334444"
+ assert scheduling_context.schedule_lambda_account is False
+
+ # second call
+ scheduling_context = run_scheduling_lambda_func.call_args_list[1].args[0]
+ assert scheduling_context.region == "us-east-1"
+ assert scheduling_context.service == "ec2"
+ assert scheduling_context.account_id == "333344445555"
+ assert scheduling_context.schedule_lambda_account is False
+
+
+@patch.object(SchedulingOrchestratorHandler, "_run_scheduling_lambda")
+def test_2accounts_1region_1service_with_local_calls_scheduler_x3(
+ run_scheduling_lambda_func: MagicMock,
+) -> None:
+ conf = get_scheduler_conf_defaults()
+ conf["scheduled_services"] = ["ec2"]
+ conf["regions"] = ["us-east-1"]
+ conf["schedule_lambda_account"] = True
+ conf["remote_account_ids"] = ["222233334444", "333344445555"]
+
+ with patch.object(
+ SchedulingOrchestratorHandler, "configuration", GlobalConfig(**conf)
+ ):
+ cloudwatch_handler = SchedulingOrchestratorHandler(
+ event=mockEvent, context=MockLambdaContext()
+ )
+ cloudwatch_handler.handle_request()
+
+ assert run_scheduling_lambda_func.call_count == 3
+
+ # first call
+ scheduling_context = run_scheduling_lambda_func.call_args_list[0].args[0]
+ assert scheduling_context.region == "us-east-1"
+ assert scheduling_context.service == "ec2"
+ assert scheduling_context.account_id == ""
+ assert scheduling_context.schedule_lambda_account is True
+
+ # second call
+ scheduling_context = run_scheduling_lambda_func.call_args_list[1].args[0]
+ assert scheduling_context.region == "us-east-1"
+ assert scheduling_context.service == "ec2"
+ assert scheduling_context.account_id == "222233334444"
+ assert scheduling_context.schedule_lambda_account is False
+
+ # third call
+ scheduling_context = run_scheduling_lambda_func.call_args_list[2].args[0]
+ assert scheduling_context.region == "us-east-1"
+ assert scheduling_context.service == "ec2"
+ assert scheduling_context.account_id == "333344445555"
+ assert scheduling_context.schedule_lambda_account is False
+
+
+@patch.object(SchedulingOrchestratorHandler, "_run_scheduling_lambda")
+def test_1region_2service_calls_scheduler_x2(
+ run_scheduling_lambda_func: MagicMock,
+) -> None:
+ conf = get_scheduler_conf_defaults()
+ conf["scheduled_services"] = ["ec2", "rds"]
+ conf["regions"] = ["us-east-1"]
+
+ with patch.object(
+ SchedulingOrchestratorHandler, "configuration", GlobalConfig(**conf)
+ ):
+ cloudwatch_handler = SchedulingOrchestratorHandler(
+ event=mockEvent, context=MockLambdaContext()
+ )
+ cloudwatch_handler.handle_request()
+
+ assert run_scheduling_lambda_func.call_count == 2
+
+ # first call
+ scheduling_context = run_scheduling_lambda_func.call_args_list[0].args[0]
+ assert scheduling_context.region == "us-east-1"
+ assert scheduling_context.service == "ec2"
+
+ # second call
+ scheduling_context = run_scheduling_lambda_func.call_args_list[1].args[0]
+ assert scheduling_context.region == "us-east-1"
+ assert scheduling_context.service == "rds"
+
+
+@patch.object(SchedulingOrchestratorHandler, "_run_scheduling_lambda")
+def test_3account_3region_3service_calls_scheduler_x27(
+ run_scheduling_lambda_func: MagicMock,
+) -> None:
+ conf = get_scheduler_conf_defaults()
+ conf["scheduled_services"] = ["ec2", "rds", "ecs"]
+ conf["regions"] = ["us-east-1", "us-east-2", "us-west-1"]
+ conf["remote_account_ids"] = ["111122223333", "222233334444", "333344445555"]
+ conf["schedule_lambda_account"] = False
+
+ with patch.object(
+ SchedulingOrchestratorHandler, "configuration", GlobalConfig(**conf)
+ ):
+ cloudwatch_handler = SchedulingOrchestratorHandler(
+ event=mockEvent, context=MockLambdaContext()
+ )
+ cloudwatch_handler.handle_request()
+
+ assert run_scheduling_lambda_func.call_count == 27
+ for index, call in enumerate(run_scheduling_lambda_func.call_args_list):
+ scheduling_context = call.args[0]
+ assert scheduling_context.region # assert exists
+ assert scheduling_context.account_id or (
+ scheduling_context.schedule_lambda_account is True
+ )
+ assert scheduling_context.service
diff --git a/source/app/tests/handler/test_scheduling_request_handler.py b/source/app/tests/handler/test_scheduling_request_handler.py
new file mode 100644
index 00000000..6a0505ea
--- /dev/null
+++ b/source/app/tests/handler/test_scheduling_request_handler.py
@@ -0,0 +1,31 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from unittest.mock import ANY, MagicMock, patch
+
+from instance_scheduler.handler.scheduling_request import SchedulingRequestHandler
+from tests.context import MockLambdaContext
+from tests.integration.helpers.schedule_helpers import quick_time
+from tests.integration.helpers.scheduling_context_builder import (
+ build_context,
+ build_scheduling_event,
+)
+
+
+@patch("instance_scheduler.handler.scheduling_request.Session")
+def test_scheduler_uses_regional_sts_endpoint(mock_session: MagicMock) -> None:
+ mock_client = MagicMock()
+ mock_session.return_value.client = mock_client
+ region_name = "executing-region"
+ mock_session.return_value.region_name = region_name
+
+ context = build_context(current_dt=quick_time(10, 0, 0), service="rds")
+ event = build_scheduling_event(context)
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.sts
+
+ mock_client.assert_called_with(
+ "sts",
+ region_name=region_name,
+ endpoint_url=f"https://sts.{region_name}.amazonaws.com",
+ config=ANY,
+ )
diff --git a/source/app/tests/integration/__init__.py b/source/app/tests/integration/__init__.py
new file mode 100644
index 00000000..161d068d
--- /dev/null
+++ b/source/app/tests/integration/__init__.py
@@ -0,0 +1,4 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+
+# this file is necessary for mypy to be able to correctly differentiate between conftest.py files
diff --git a/source/app/tests/integration/conftest.py b/source/app/tests/integration/conftest.py
new file mode 100644
index 00000000..a91dbe23
--- /dev/null
+++ b/source/app/tests/integration/conftest.py
@@ -0,0 +1,148 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from collections.abc import Iterator
+from typing import TYPE_CHECKING
+
+import boto3
+from moto import mock_rds, mock_resourcegroupstaggingapi
+from pytest import fixture
+
+from instance_scheduler.schedulers.instance_states import InstanceStates
+from instance_scheduler.util.app_env import AppEnv
+from tests import ami
+from tests.logger import MockLogger
+
+if TYPE_CHECKING:
+ from mypy_boto3_dynamodb import DynamoDBClient
+ from mypy_boto3_ec2.client import EC2Client
+ from mypy_boto3_rds.client import RDSClient
+ from mypy_boto3_rds.type_defs import CreateDBInstanceResultTypeDef
+else:
+ DynamoDBClient = object
+ EC2Client = object
+ RDSClient = object
+ CreateDBInstanceResultTypeDef = object
+
+
+@fixture(autouse=True)
+def moto_logs_autouse(moto_logs: None) -> Iterator[None]:
+ yield
+
+
+@fixture(autouse=True)
+def mock_log_group_autouse(mock_log_group: None) -> None:
+ """noop"""
+
+
+@fixture(autouse=True)
+def moto_sns_autouse(moto_sns: None) -> Iterator[None]:
+ yield
+
+
+@fixture(autouse=True)
+def mock_topic_autouse(mock_topic: None) -> None:
+ """noop"""
+
+
+@fixture(autouse=True)
+def moto_sts_autouse(moto_sts: None) -> Iterator[None]:
+ yield
+
+
+@fixture
+def moto_rds() -> Iterator[None]:
+ with mock_rds():
+ yield
+
+
+@fixture
+def moto_resource_group_tagging_api() -> Iterator[None]:
+ with mock_resourcegroupstaggingapi():
+ yield
+
+
+@fixture
+def ec2_instance(moto_ec2: None) -> Iterator[str]:
+ ec2_client: EC2Client = boto3.client("ec2")
+ instance_id: str = ec2_client.run_instances(ImageId=ami, MinCount=1, MaxCount=1)[
+ "Instances"
+ ][0]["InstanceId"]
+ ec2_client.create_tags(
+ Resources=[instance_id], Tags=[{"Key": "Schedule", "Value": "test-schedule"}]
+ )
+ yield instance_id
+
+
+@fixture
+def rds_instance(
+ moto_rds: None, moto_resource_group_tagging_api: None
+) -> Iterator[str]:
+ instance_id = "rds-test-instance"
+ rds_client: RDSClient = boto3.client("rds")
+ result: CreateDBInstanceResultTypeDef = rds_client.create_db_instance(
+ DBInstanceIdentifier=instance_id,
+ DBInstanceClass="db.m5.large",
+ Engine="postgres",
+ )
+ instance_arn = result["DBInstance"]["DBInstanceArn"]
+ rds_client.add_tags_to_resource(
+ ResourceName=instance_arn, Tags=[{"Key": "Schedule", "Value": "test-schedule"}]
+ )
+ yield instance_id
+
+
+@fixture
+def rds_cluster(moto_rds: None, moto_resource_group_tagging_api: None) -> Iterator[str]:
+ cluster_id = "rds-test-cluster"
+ engine = "aurora-mysql"
+ rds: RDSClient = boto3.client("rds")
+ result = rds.create_db_cluster(
+ DBClusterIdentifier=cluster_id,
+ Engine=engine,
+ MasterUsername="admin",
+ MasterUserPassword="password",
+ )
+ arn = result["DBCluster"]["DBClusterArn"]
+ rds.add_tags_to_resource(
+ ResourceName=arn, Tags=[{"Key": "Schedule", "Value": "test-schedule"}]
+ )
+ rds.create_db_instance(
+ DBInstanceIdentifier="rds-test-instance",
+ DBClusterIdentifier=cluster_id,
+ Engine=engine,
+ DBInstanceClass="db.m5.large",
+ )
+ yield cluster_id
+
+
+@fixture
+def state_table(moto_dynamodb: None, app_env: AppEnv) -> str:
+ state_table_name = app_env.state_table_name
+ dynamo_client: DynamoDBClient = boto3.client("dynamodb")
+ dynamo_client.create_table(
+ TableName=state_table_name,
+ AttributeDefinitions=[
+ {"AttributeName": "service", "AttributeType": "S"},
+ {"AttributeName": "account-region", "AttributeType": "S"},
+ ],
+ KeySchema=[
+ {"AttributeName": "service", "KeyType": "HASH"},
+ {"AttributeName": "account-region", "KeyType": "RANGE"},
+ ],
+ BillingMode="PAY_PER_REQUEST",
+ )
+ return state_table_name
+
+
+@fixture
+def ec2_instance_states(state_table: str) -> InstanceStates:
+ instance_states = InstanceStates(state_table, "ec2", MockLogger())
+ instance_states.load(account="123456789012", region="us-east-1")
+ return instance_states
+
+
+@fixture
+def rds_instance_states(state_table: str) -> InstanceStates:
+ instance_states = InstanceStates(state_table, "rds", MockLogger())
+ instance_states.load(account="123456789012", region="us-east-1")
+ return instance_states
diff --git a/source/app/tests/integration/helpers/__init__.py b/source/app/tests/integration/helpers/__init__.py
new file mode 100644
index 00000000..04f8b7b7
--- /dev/null
+++ b/source/app/tests/integration/helpers/__init__.py
@@ -0,0 +1,2 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
diff --git a/source/app/tests/integration/helpers/boto_client_helpers.py b/source/app/tests/integration/helpers/boto_client_helpers.py
new file mode 100644
index 00000000..b2966237
--- /dev/null
+++ b/source/app/tests/integration/helpers/boto_client_helpers.py
@@ -0,0 +1,25 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from typing import Any
+
+import boto3
+from mypy_boto3_sts import STSClient
+
+
+def client_in_account_region(
+ client: str, account: str, region: str = "us-east-1"
+) -> Any:
+ sts: STSClient = boto3.client("sts")
+ token = sts.assume_role(
+ RoleArn=f"arn:aws:iam::{account}:role/moto-role",
+ RoleSessionName="create-instances-session",
+ ExternalId="create-instances-external-id",
+ )["Credentials"]
+
+ return boto3.client(
+ client,
+ aws_access_key_id=token["AccessKeyId"],
+ aws_secret_access_key=token["SecretAccessKey"],
+ aws_session_token=token["SessionToken"],
+ region_name=region,
+ )
diff --git a/source/app/tests/integration/helpers/ec2_helpers.py b/source/app/tests/integration/helpers/ec2_helpers.py
new file mode 100644
index 00000000..8fdfbed5
--- /dev/null
+++ b/source/app/tests/integration/helpers/ec2_helpers.py
@@ -0,0 +1,57 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from typing import Optional
+
+import boto3
+from mypy_boto3_ec2.client import EC2Client
+from mypy_boto3_ec2.type_defs import (
+ DescribeInstancesResultTypeDef,
+ DescribeInstanceStatusResultTypeDef,
+ TagTypeDef,
+)
+
+from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from tests import ami
+from tests.integration.helpers.boto_client_helpers import client_in_account_region
+
+
+def create_ec2_instances(
+ count: int,
+ schedule: InstanceSchedule,
+ account: str = "123456789012",
+ region: str = "us-east-1",
+) -> tuple[str, ...]:
+ ec2_client: EC2Client = client_in_account_region("ec2", account, region)
+ create_response = ec2_client.run_instances(
+ ImageId=ami, MinCount=count, MaxCount=count
+ )
+ instance_ids = [instance["InstanceId"] for instance in create_response["Instances"]]
+ ec2_client.create_tags(
+ Resources=instance_ids, Tags=[{"Key": "Schedule", "Value": schedule.name}]
+ )
+
+ return tuple(instance_ids)
+
+
+def get_current_state(instance_id: str, ec2_client: Optional[EC2Client] = None) -> str:
+ client: EC2Client
+ if ec2_client:
+ client = ec2_client
+ else:
+ client = boto3.client("ec2")
+ describe_response: DescribeInstanceStatusResultTypeDef = (
+ client.describe_instance_status(
+ InstanceIds=[instance_id], IncludeAllInstances=True
+ )
+ )
+
+ return describe_response["InstanceStatuses"][0]["InstanceState"]["Name"]
+
+
+def get_tags(instance_id: str) -> list[TagTypeDef]:
+ ec2_client: EC2Client = boto3.client("ec2")
+ describe_response: DescribeInstancesResultTypeDef = ec2_client.describe_instances(
+ InstanceIds=[instance_id]
+ )
+
+ return describe_response["Reservations"][0]["Instances"][0]["Tags"]
diff --git a/source/app/tests/integration/helpers/global_config.py b/source/app/tests/integration/helpers/global_config.py
new file mode 100644
index 00000000..23a71cb5
--- /dev/null
+++ b/source/app/tests/integration/helpers/global_config.py
@@ -0,0 +1,56 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from typing import Optional
+from zoneinfo import ZoneInfo
+
+from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler.configuration.scheduler_config import GlobalConfig
+
+
+def build_global_config(
+ schedules: dict[str, InstanceSchedule],
+ remote_account_ids: Optional[list[str]] = None,
+ scheduled_services: Optional[list[str]] = None,
+ regions: Optional[list[str]] = None,
+ tag_name: str = "Schedule",
+ default_timezone: str = "UTC",
+ schedule_clusters: bool = False,
+ trace: bool = False,
+ enable_ssm_maintenance_windows: bool = False,
+ use_metrics: bool = False,
+ namespace: str = "namespace",
+ aws_partition: str = "aws",
+ scheduler_role_name: str = "scheduler_role",
+ organization_id: str = "",
+ schedule_lambda_account: bool = True,
+ create_rds_snapshot: bool = False,
+ started_tags: str = "",
+ stopped_tags: str = "",
+) -> GlobalConfig:
+ if remote_account_ids is None:
+ remote_account_ids = []
+ if scheduled_services is None:
+ scheduled_services = ["ec2"]
+ if regions is None:
+ regions = ["us-east-1"]
+
+ return GlobalConfig(
+ schedules=schedules,
+ remote_account_ids=remote_account_ids,
+ scheduled_services=scheduled_services,
+ regions=regions,
+ tag_name=tag_name,
+ default_timezone=ZoneInfo(default_timezone),
+ schedule_clusters=schedule_clusters,
+ trace=trace,
+ enable_ssm_maintenance_windows=enable_ssm_maintenance_windows,
+ use_metrics=use_metrics,
+ namespace=namespace,
+ aws_partition=aws_partition,
+ scheduler_role_name=scheduler_role_name,
+ organization_id=organization_id,
+ schedule_lambda_account=schedule_lambda_account,
+ create_rds_snapshot=create_rds_snapshot,
+ started_tags=started_tags,
+ stopped_tags=stopped_tags,
+ )
diff --git a/source/app/tests/integration/helpers/rds_helpers.py b/source/app/tests/integration/helpers/rds_helpers.py
new file mode 100644
index 00000000..993aefa4
--- /dev/null
+++ b/source/app/tests/integration/helpers/rds_helpers.py
@@ -0,0 +1,22 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from typing import TYPE_CHECKING
+
+import boto3
+
+if TYPE_CHECKING:
+ from mypy_boto3_rds import RDSClient
+else:
+ RDSClient = object
+
+
+def get_rds_instance_state(instance_id: str) -> str:
+ rds: RDSClient = boto3.client("rds")
+ response = rds.describe_db_instances(DBInstanceIdentifier=instance_id)
+ return response["DBInstances"][0]["DBInstanceStatus"]
+
+
+def get_rds_cluster_state(cluster_id: str) -> str:
+ rds: RDSClient = boto3.client("rds")
+ response = rds.describe_db_clusters(DBClusterIdentifier=cluster_id)
+ return response["DBClusters"][0]["Status"]
diff --git a/source/app/tests/integration/helpers/schedule_helpers.py b/source/app/tests/integration/helpers/schedule_helpers.py
new file mode 100644
index 00000000..7f5628e0
--- /dev/null
+++ b/source/app/tests/integration/helpers/schedule_helpers.py
@@ -0,0 +1,13 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import datetime
+
+
+def at_time(
+ time: datetime.time, date: datetime.date = datetime.date(2023, 5, 31)
+) -> datetime.datetime:
+ return datetime.datetime.combine(date, time, datetime.timezone.utc)
+
+
+def quick_time(hrs: int, minutes: int, seconds: int) -> datetime.datetime:
+ return at_time(datetime.time(hrs, minutes, seconds))
diff --git a/source/app/tests/integration/helpers/scheduling_context_builder.py b/source/app/tests/integration/helpers/scheduling_context_builder.py
new file mode 100644
index 00000000..e009eb0d
--- /dev/null
+++ b/source/app/tests/integration/helpers/scheduling_context_builder.py
@@ -0,0 +1,132 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from datetime import datetime, time
+from typing import Optional
+from zoneinfo import ZoneInfo
+
+from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler.configuration.running_period import RunningPeriod
+from instance_scheduler.configuration.running_period_dict_element import (
+ RunningPeriodDictElement,
+)
+from instance_scheduler.configuration.scheduling_context import (
+ SchedulingContext,
+ TagTemplate,
+)
+from instance_scheduler.handler.scheduling_request import SchedulerRequest
+
+
+def default_test_schedules() -> dict[str, InstanceSchedule]:
+ schedule = default_test_schedule()
+ return {schedule.name: schedule}
+
+
+def default_test_schedule() -> InstanceSchedule:
+ return InstanceSchedule(
+ name="test-schedule",
+ periods=default_test_periods(),
+ )
+
+
+def default_test_periods() -> list[RunningPeriodDictElement]:
+ return [
+ {
+ "period": RunningPeriod(
+ name="test-period",
+ begintime=time(10, 0, 0),
+ endtime=time(20, 0, 0),
+ )
+ }
+ ]
+
+
+def custom_schedule(
+ periods: list[RunningPeriodDictElement] = default_test_periods(),
+ # mutable warning is desired behavior here as an empty period list should NOT be resolved to the default
+ timezone: str = "UTC",
+ override_status: Optional[str] = None,
+ description: Optional[str] = None,
+ use_metrics: Optional[bool] = None,
+ stop_new_instances: Optional[bool] = None,
+ use_maintenance_window: Optional[bool] = False,
+ ssm_maintenance_window: Optional[str] = None,
+ enforced: Optional[bool] = False,
+ hibernate: Optional[bool] = False,
+ retain_running: Optional[bool] = False,
+) -> dict[str, InstanceSchedule]:
+ return {
+ "test-schedule": InstanceSchedule(
+ name="test-schedule",
+ periods=periods,
+ timezone=timezone,
+ override_status=override_status,
+ description=description,
+ use_metrics=use_metrics,
+ stop_new_instances=stop_new_instances,
+ use_maintenance_window=use_maintenance_window,
+ ssm_maintenance_window=ssm_maintenance_window,
+ enforced=enforced,
+ hibernate=hibernate,
+ retain_running=retain_running,
+ )
+ }
+
+
+def build_context(
+ current_dt: datetime,
+ schedules: dict[str, InstanceSchedule] = None, # type: ignore[assignment]
+ account_id: str = "",
+ service: str = "ec2",
+ region: str = "us-east-1",
+ tag_name: str = "Schedule",
+ default_timezone: str = "UTC",
+ schedule_clusters: bool = False,
+ trace: bool = False,
+ enable_ssm_maintenance_windows: bool = False,
+ use_metrics: bool = False,
+ namespace: str = "namespace",
+ aws_partition: str = "aws",
+ scheduler_role_name: str = "scheduler_role",
+ organization_id: str = "",
+ schedule_lambda_account: bool = True,
+ create_rds_snapshot: bool = False,
+ started_tags: Optional[list[TagTemplate]] = None,
+ stopped_tags: Optional[list[TagTemplate]] = None,
+) -> SchedulingContext:
+ """abstraction layer on SchedulingContextConstructor that provides testing defaults for most values"""
+ if schedules is None:
+ schedules = default_test_schedules()
+ if started_tags is None:
+ started_tags = []
+ if stopped_tags is None:
+ stopped_tags = []
+
+ return SchedulingContext(
+ current_dt=current_dt,
+ schedules=schedules,
+ account_id=account_id,
+ service=service,
+ region=region,
+ tag_name=tag_name,
+ default_timezone=ZoneInfo(default_timezone),
+ schedule_clusters=schedule_clusters,
+ trace=trace,
+ enable_ssm_maintenance_windows=enable_ssm_maintenance_windows,
+ use_metrics=use_metrics,
+ namespace=namespace,
+ aws_partition=aws_partition,
+ scheduler_role_name=scheduler_role_name,
+ organization_id=organization_id,
+ schedule_lambda_account=schedule_lambda_account,
+ create_rds_snapshot=create_rds_snapshot,
+ started_tags=started_tags,
+ stopped_tags=stopped_tags,
+ )
+
+
+def build_scheduling_event(scheduling_context: SchedulingContext) -> SchedulerRequest:
+ return {
+ "action": "scheduler:run",
+ "configuration": scheduling_context.to_dict(),
+ "dispatch_time": "2023-05-12 14:55:10.600619",
+ }
diff --git a/source/app/tests/integration/ops_metrics/__init__.py b/source/app/tests/integration/ops_metrics/__init__.py
new file mode 100644
index 00000000..04f8b7b7
--- /dev/null
+++ b/source/app/tests/integration/ops_metrics/__init__.py
@@ -0,0 +1,2 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
diff --git a/source/app/tests/integration/ops_metrics/conftest.py b/source/app/tests/integration/ops_metrics/conftest.py
new file mode 100644
index 00000000..d7e65899
--- /dev/null
+++ b/source/app/tests/integration/ops_metrics/conftest.py
@@ -0,0 +1,33 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import uuid
+from typing import Iterator
+from unittest.mock import MagicMock, patch
+
+from _pytest.fixtures import fixture
+from requests import Response
+
+solution_metrics_uuid = uuid.UUID("3d522722-236f-4484-bbd7-e9b1da1bb347")
+
+
+@fixture
+def metrics_enabled() -> Iterator[None]:
+ with patch(
+ "instance_scheduler.ops_metrics.metrics.should_collect_metric"
+ ) as should_collect_metrics_func:
+ with patch(
+ "instance_scheduler.ops_metrics.metrics._get_deployment_uuid"
+ ) as get_deployment_uuid_func:
+ should_collect_metrics_func.return_value = True
+ get_deployment_uuid_func.return_value = solution_metrics_uuid
+ yield
+
+
+@fixture
+def mock_metrics_endpoint(metrics_enabled: None) -> Iterator[MagicMock]:
+ with patch("requests.post") as post_request_func:
+ post_response = Response()
+ post_response.status_code = 200
+ post_request_func.return_value = post_response
+
+ yield post_request_func
diff --git a/source/app/tests/integration/ops_metrics/test_cli_metrics.py b/source/app/tests/integration/ops_metrics/test_cli_metrics.py
new file mode 100644
index 00000000..f46c33da
--- /dev/null
+++ b/source/app/tests/integration/ops_metrics/test_cli_metrics.py
@@ -0,0 +1,41 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import datetime
+import json
+from unittest.mock import MagicMock
+from zoneinfo import ZoneInfo
+
+from freezegun.api import freeze_time
+
+from instance_scheduler.handler.cli import CliHandler
+from instance_scheduler.util.app_env import AppEnv
+from tests.context import MockLambdaContext
+from tests.integration.ops_metrics.conftest import solution_metrics_uuid
+from tests.logger import MockLogger
+
+
+@freeze_time(datetime.datetime(2023, 6, 12, 12, 0, 0, tzinfo=ZoneInfo("UTC")))
+def test_cli_handler_sends_expected_metric(
+ mock_metrics_endpoint: MagicMock, app_env: AppEnv
+) -> None:
+ action = "my-action"
+ parameters = {"my_key": "my-value"}
+ handler = CliHandler(
+ {"action": action, "parameters": parameters},
+ MockLambdaContext(),
+ )
+ handler._logger = MockLogger()
+ handler.handle_request()
+
+ expected_metric = {
+ "TimeStamp": "2023-06-12 12:00:00",
+ "UUID": str(solution_metrics_uuid),
+ "Solution": app_env.solution_id,
+ "Version": app_env.solution_version,
+ "Event_Name": "cli_request",
+ "Context": {"command_used": action},
+ }
+
+ assert mock_metrics_endpoint.call_count == 1
+ json_payload = mock_metrics_endpoint.call_args[1]["data"]
+ assert json.loads(json_payload) == expected_metric
diff --git a/source/app/tests/integration/ops_metrics/test_configuration_description_metrics.py b/source/app/tests/integration/ops_metrics/test_configuration_description_metrics.py
new file mode 100644
index 00000000..eb82e6a9
--- /dev/null
+++ b/source/app/tests/integration/ops_metrics/test_configuration_description_metrics.py
@@ -0,0 +1,144 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import json
+from datetime import datetime, time
+from os import environ
+from unittest.mock import MagicMock, patch
+from zoneinfo import ZoneInfo
+
+from freezegun import freeze_time
+
+from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler.configuration.running_period import RunningPeriod
+from instance_scheduler.configuration.running_period_dict_element import (
+ RunningPeriodDictElement,
+)
+from instance_scheduler.configuration.scheduler_config import GlobalConfig
+from instance_scheduler.handler.collect_configuration_description import (
+ CollectConfigurationDescription,
+ CollectConfigurationMetricsRequest,
+)
+from instance_scheduler.util.app_env import AppEnv
+from tests.context import MockLambdaContext
+from tests.integration.ops_metrics.conftest import solution_metrics_uuid
+
+mockEvent: CollectConfigurationMetricsRequest = {
+ "scheduled_action": "collect_configuration_metrics",
+}
+
+periods: list[RunningPeriodDictElement] = [
+ RunningPeriodDictElement(
+ period=RunningPeriod(
+ name="test-period",
+ begintime=time(10, 0, 0),
+ endtime=time(20, 0, 0),
+ )
+ )
+]
+
+global_config = GlobalConfig(
+ scheduled_services=["ec2"],
+ schedule_clusters=False,
+ tag_name="Schedule",
+ regions=[],
+ default_timezone=ZoneInfo("Asia/Hong_Kong"),
+ schedules={
+ "all-flags": InstanceSchedule(
+ name="all-flags",
+ periods=periods,
+ override_status="running",
+ use_metrics=True,
+ stop_new_instances=True,
+ use_maintenance_window=True,
+ enforced=True,
+ hibernate=True,
+ retain_running=True,
+ timezone="Asia/Hong_Kong",
+ ),
+ "no-flags-cfn": InstanceSchedule(
+ name="no-flags-cfn",
+ periods=periods,
+ configured_in_stack="some-stack-arn",
+ timezone="UTC",
+ ),
+ "non-default-tz-cfn": InstanceSchedule(
+ name="non-default-tz-cfn",
+ periods=periods,
+ configured_in_stack="some-stack-arn",
+ timezone="UTC",
+ ),
+ "explicit-tz-matches-default": InstanceSchedule(
+ name="explicit-tz-matches-default",
+ periods=periods,
+ timezone="Asia/Hong_Kong", # should not be counted by tz metric
+ ),
+ },
+ trace=False,
+ enable_ssm_maintenance_windows=True,
+ use_metrics=True,
+ schedule_lambda_account=True,
+ create_rds_snapshot=False,
+ started_tags="non-null tag",
+ stopped_tags="",
+ scheduler_role_name="Scheduler-Role",
+ namespace="dev",
+ organization_id="",
+ aws_partition="aws",
+ remote_account_ids=[],
+)
+
+env = {
+ "START_TAGS": "non-null tag",
+ "STOP_TAGS": "",
+ "SCHEDULER_FREQUENCY": "10",
+ "ENABLE_AWS_ORGANIZATIONS": "False",
+ "ENABLE_EC2_SSM_MAINTENANCE_WINDOWS": "True",
+}
+
+
+@patch.dict(environ, env)
+@freeze_time(datetime(2023, 6, 12, 12, 0, 0, tzinfo=ZoneInfo("UTC")))
+def test_collect_configuration_description_metrics_collects_expected_metric(
+ mock_metrics_endpoint: MagicMock, app_env: AppEnv
+) -> None:
+ with patch(
+ "instance_scheduler.configuration.get_global_configuration"
+ ) as global_config_access_point:
+ global_config_access_point.return_value = global_config
+ handler = CollectConfigurationDescription(mockEvent, MockLambdaContext())
+ handler.handle_request()
+
+ expected_metric = {
+ "TimeStamp": "2023-06-12 12:00:00",
+ "UUID": str(solution_metrics_uuid),
+ "Solution": app_env.solution_id,
+ "Version": app_env.solution_version,
+ "Event_Name": "configuration_description",
+ "Context": {
+ "num_schedules": 4,
+ "num_cfn_schedules": 2,
+ "default_timezone": "Asia/Hong_Kong",
+ "schedule_aurora_clusters": False,
+ "create_rds_snapshots": False,
+ "schedule_interval_minutes": 10,
+ "memory_size_mb": 128, # memory size from MockLambdaContext
+ "using_organizations": False,
+ "enable_ec2_ssm_maintenance_windows": True,
+ "num_started_tags": 1,
+ "num_stopped_tags": 0,
+ "schedule_flag_counts": {
+ "stop_new_instances": 1,
+ "enforced": 1,
+ "retain_running": 1,
+ "hibernate": 1,
+ "override": 1,
+ "use_ssm_maintenance_window": 1,
+ "use_metrics": 1,
+ "non_default_timezone": 2,
+ },
+ },
+ }
+
+ assert mock_metrics_endpoint.call_count == 1
+ json_payload = mock_metrics_endpoint.call_args[1]["data"]
+ assert json.loads(json_payload) == expected_metric
diff --git a/source/app/tests/integration/ops_metrics/test_deployment_description_metrics.py b/source/app/tests/integration/ops_metrics/test_deployment_description_metrics.py
new file mode 100644
index 00000000..5a6db7e5
--- /dev/null
+++ b/source/app/tests/integration/ops_metrics/test_deployment_description_metrics.py
@@ -0,0 +1,54 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import json
+from datetime import datetime
+from unittest.mock import MagicMock, patch
+from zoneinfo import ZoneInfo
+
+from freezegun import freeze_time
+
+from instance_scheduler.handler.scheduling_orchestrator import (
+ OrchestrationRequest,
+ SchedulingOrchestratorHandler,
+)
+from instance_scheduler.util.app_env import AppEnv
+from tests.context import MockLambdaContext
+from tests.integration.ops_metrics.conftest import solution_metrics_uuid
+from tests.util.test_global_config import sample_global_config
+
+mockEvent: OrchestrationRequest = {"scheduled_action": "run_orchestrator"}
+
+
+@patch.object(SchedulingOrchestratorHandler, "_run_scheduling_lambda")
+@freeze_time(datetime(2023, 6, 12, 12, 0, 0, tzinfo=ZoneInfo("UTC")))
+def test_orchestrator_sends_expected_metric(
+ run_lambda_func: MagicMock, mock_metrics_endpoint: MagicMock, app_env: AppEnv
+) -> None:
+ global_config = sample_global_config()
+ global_config.regions = ["us-east-1", "us-east-2", "us-west-2"]
+ global_config.scheduled_services = ["ec2", "rds"]
+ global_config.remote_account_ids = ["222233334444", "333344445555"]
+ global_config.schedule_lambda_account = True
+
+ with patch.object(SchedulingOrchestratorHandler, "configuration", global_config):
+ handler = SchedulingOrchestratorHandler(
+ event=mockEvent, context=MockLambdaContext()
+ )
+ handler.handle_request()
+
+ expected_metric = {
+ "TimeStamp": "2023-06-12 12:00:00",
+ "UUID": str(solution_metrics_uuid),
+ "Solution": app_env.solution_id,
+ "Version": app_env.solution_version,
+ "Event_Name": "deployment_description",
+ "Context": {
+ "services": ["ec2", "rds"],
+ "regions": ["us-east-1", "us-east-2", "us-west-2"],
+ "num_accounts": 3, # local account + 2 remote
+ },
+ }
+
+ assert mock_metrics_endpoint.call_count == 1
+ json_payload = mock_metrics_endpoint.call_args[1]["data"]
+ assert json.loads(json_payload) == expected_metric
diff --git a/source/app/tests/integration/ops_metrics/test_instance_count_metrics.py b/source/app/tests/integration/ops_metrics/test_instance_count_metrics.py
new file mode 100644
index 00000000..6cba9c28
--- /dev/null
+++ b/source/app/tests/integration/ops_metrics/test_instance_count_metrics.py
@@ -0,0 +1,120 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import json
+from datetime import datetime, time
+from typing import Any
+from unittest.mock import MagicMock, patch
+from zoneinfo import ZoneInfo
+
+import boto3
+from freezegun import freeze_time
+from mypy_boto3_ec2.client import EC2Client
+
+from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler.configuration.running_period import RunningPeriod
+from instance_scheduler.configuration.running_period_dict_element import (
+ RunningPeriodDictElement,
+)
+from instance_scheduler.handler.scheduling_request import SchedulingRequestHandler
+from instance_scheduler.ops_metrics import GatheringFrequency
+from instance_scheduler.ops_metrics.metric_type.instance_count_metric import (
+ InstanceCountMetric,
+)
+from instance_scheduler.schedulers.instance_states import InstanceStates
+from instance_scheduler.util.app_env import AppEnv
+from tests import ami
+from tests.context import MockLambdaContext
+from tests.integration.helpers.schedule_helpers import quick_time
+from tests.integration.helpers.scheduling_context_builder import (
+ build_context,
+ build_scheduling_event,
+)
+from tests.integration.ops_metrics.conftest import solution_metrics_uuid
+
+schedule_1 = InstanceSchedule(
+ name="sched_1",
+ periods=[
+ RunningPeriodDictElement(
+ period=RunningPeriod(name="stop", begintime=time(12, 0, 0))
+ )
+ ],
+)
+
+schedule_2 = InstanceSchedule(
+ name="sched_2",
+ periods=[
+ RunningPeriodDictElement(
+ period=RunningPeriod(name="start", endtime=time(12, 0, 0))
+ )
+ ],
+)
+
+
+def create_test_instances(count: int, schedule: InstanceSchedule) -> list[str]:
+ ec2_client: EC2Client = boto3.client("ec2")
+ create_response = ec2_client.run_instances(
+ ImageId=ami, MinCount=count, MaxCount=count
+ )
+ instance_ids = [instance["InstanceId"] for instance in create_response["Instances"]]
+ ec2_client.create_tags(
+ Resources=instance_ids, Tags=[{"Key": "Schedule", "Value": schedule.name}]
+ )
+
+ return instance_ids
+
+
+def get_sent_instance_count_metric(metrics_endpoint: MagicMock) -> Any:
+ desired_metric: dict[str, Any] = {}
+ for call_args in metrics_endpoint.call_args_list:
+ json_payload = call_args[1]["data"]
+ sent_metric = json.loads(json_payload)
+
+ if sent_metric["Event_Name"] == "instance_count":
+ if desired_metric:
+ raise Exception("metric sent multiple times")
+ desired_metric = sent_metric
+
+ if not desired_metric:
+ raise Exception("metric not found")
+ return desired_metric
+
+
+def test_instance_count_metric_is_daily_metric() -> None:
+ assert InstanceCountMetric.collection_frequency is GatheringFrequency.DAILY
+
+
+@patch("instance_scheduler.schedulers.instance_scheduler.should_collect_metric")
+@freeze_time(datetime(2023, 6, 12, 12, 0, 0, tzinfo=ZoneInfo("UTC")))
+def test_scheduling_execution_sends_expected_instance_count_metric(
+ should_collect_metrics_func: MagicMock,
+ mock_metrics_endpoint: MagicMock,
+ moto_ec2: None,
+ ec2_instance_states: InstanceStates,
+ app_env: AppEnv,
+) -> None:
+ should_collect_metrics_func.return_value = True
+
+ create_test_instances(5, schedule_1)
+ create_test_instances(10, schedule_2)
+
+ context = build_context(current_dt=quick_time(10, 0, 0))
+ event = build_scheduling_event(context)
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ expected_metric = {
+ "TimeStamp": "2023-06-12 12:00:00",
+ "UUID": str(solution_metrics_uuid),
+ "Solution": app_env.solution_id,
+ "Version": app_env.solution_version,
+ "Event_Name": "instance_count",
+ "Context": {
+ "service": "ec2",
+ "region": "us-east-1",
+ "num_instances": 15,
+ "num_schedules": 2,
+ },
+ }
+
+ sent_metric = get_sent_instance_count_metric(mock_metrics_endpoint)
+ assert sent_metric == expected_metric
diff --git a/source/app/tests/integration/ops_metrics/test_metrics_handler.py b/source/app/tests/integration/ops_metrics/test_metrics_handler.py
new file mode 100644
index 00000000..b4cc95f1
--- /dev/null
+++ b/source/app/tests/integration/ops_metrics/test_metrics_handler.py
@@ -0,0 +1,142 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import json
+import uuid
+from dataclasses import dataclass
+from datetime import datetime, timedelta
+from functools import wraps
+from os import environ
+from typing import Any, Callable, ClassVar, TypeVar, cast
+from unittest.mock import MagicMock, patch
+from zoneinfo import ZoneInfo
+
+from freezegun import freeze_time
+
+from instance_scheduler.ops_metrics import GatheringFrequency, metrics
+from instance_scheduler.ops_metrics.metric_type.ops_metric import OpsMetric
+from instance_scheduler.ops_metrics.metrics import collect_metric, should_collect_metric
+from instance_scheduler.util.app_env import AppEnv
+from tests.integration.ops_metrics.conftest import solution_metrics_uuid
+from tests.logger import MockLogger
+
+
+@dataclass(frozen=True)
+class UnlimitedTestMetric(OpsMetric):
+ collection_frequency: ClassVar[GatheringFrequency] = GatheringFrequency.UNLIMITED
+ event_name: ClassVar[str] = "unlimited-metrics"
+
+
+@dataclass(frozen=True)
+class DailyTestMetric(OpsMetric):
+ collection_frequency: ClassVar[GatheringFrequency] = GatheringFrequency.DAILY
+ event_name: ClassVar[str] = "daily-metrics"
+
+
+FuncT = TypeVar("FuncT", bound=Callable[..., Any])
+
+
+def metrics_uuid(metric_uuid: uuid.UUID) -> Callable[[FuncT], FuncT]:
+ def decorator(func_to_decorate: FuncT) -> FuncT:
+ @wraps(func_to_decorate)
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
+ print("metric uuid: {}".format(metric_uuid))
+ with patch(
+ "instance_scheduler.ops_metrics.metrics._get_deployment_uuid"
+ ) as solution_id_func:
+ solution_id_func.return_value = metric_uuid
+ func_to_decorate(*args, **kwargs)
+
+ return cast(FuncT, wrapper)
+
+ return decorator
+
+
+@patch.dict(environ, {"SEND_METRICS": "False"})
+@metrics_uuid(uuid.uuid4())
+def test_metrics_not_collected_when_disabled() -> None:
+ assert not should_collect_metric(UnlimitedTestMetric(), MockLogger())
+
+
+@patch.dict(environ, {"SEND_METRICS": "True"})
+@metrics_uuid(uuid.uuid4())
+def test_unlimited_metric_should_be_sent() -> None:
+ assert should_collect_metric(UnlimitedTestMetric, MockLogger())
+
+
+@patch.dict(environ, {"SEND_METRICS": "True"})
+@metrics_uuid(uuid.uuid4())
+def test_daily_metric_should_only_be_sent_once_daily() -> None:
+ minutes_in_day = 1440
+ start_of_day = datetime(2023, 6, 23, 0, 0, 0)
+
+ for interval in [5, 30, 60]: # test intervals of 5, 30, and 60 minutes
+ num_metrics_gathered = 0
+ for offset in range(0, minutes_in_day, interval):
+ sim_time = start_of_day + timedelta(minutes=offset)
+ with patch.dict(
+ environ, {"SCHEDULER_FREQUENCY": str(interval)}
+ ), freeze_time(sim_time):
+ if should_collect_metric(DailyTestMetric, MockLogger()):
+ num_metrics_gathered += 1
+
+ assert (
+ num_metrics_gathered == 1
+ ), "failed to gather specified number of metrics with interval:{} see output log for uuid used".format(
+ interval
+ )
+
+
+@metrics_uuid(uuid.uuid4())
+def test_collect_metric_does_nothing_when_should_collect_returns_false(
+ mock_metrics_endpoint: MagicMock,
+) -> None:
+ with patch(
+ "instance_scheduler.ops_metrics.metrics.should_collect_metric"
+ ) as should_collect_metric_func:
+ should_collect_metric_func.return_value = False
+ collect_metric(metric=UnlimitedTestMetric(), logger=MockLogger())
+ assert mock_metrics_endpoint.call_count == 0
+
+
+@freeze_time(datetime(2023, 6, 23, 10, 0, 5, tzinfo=ZoneInfo("UTC")))
+def test_collect_metric_sends_metric_when_should_collect_returns_true(
+ mock_metrics_endpoint: MagicMock, app_env: AppEnv
+) -> None:
+ with patch(
+ "instance_scheduler.ops_metrics.metrics.should_collect_metric"
+ ) as should_collect_metric_func:
+ should_collect_metric_func.return_value = True
+ collect_metric(metric=UnlimitedTestMetric(), logger=MockLogger())
+
+ expected_data = json.dumps(
+ {
+ "TimeStamp": "2023-06-23 10:00:05",
+ "UUID": str(solution_metrics_uuid),
+ "Solution": app_env.solution_id,
+ "Version": app_env.solution_version,
+ "Event_Name": "unlimited-metrics",
+ "Context": {},
+ },
+ indent=0,
+ )
+
+ expected_headers = {
+ "content-type": "application/json",
+ "content-length": str(len(expected_data)),
+ }
+
+ mock_metrics_endpoint.assert_called_once_with(
+ app_env.anonymous_metrics_url,
+ data=expected_data,
+ headers=expected_headers,
+ timeout=300,
+ )
+
+
+@patch("instance_scheduler.ops_metrics.metrics._deployment_uuid_from_ssm")
+def test_deployment_uuid_is_cached(deployment_uuid_func: MagicMock) -> None:
+ logger = MockLogger()
+ metrics._get_deployment_uuid(logger)
+ metrics._get_deployment_uuid(logger)
+
+ assert deployment_uuid_func.call_count == 1
diff --git a/source/app/tests/integration/ops_metrics/test_scheduling_action_metrics.py b/source/app/tests/integration/ops_metrics/test_scheduling_action_metrics.py
new file mode 100644
index 00000000..d294c2ca
--- /dev/null
+++ b/source/app/tests/integration/ops_metrics/test_scheduling_action_metrics.py
@@ -0,0 +1,186 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import json
+from datetime import datetime, time
+from typing import Any
+from unittest.mock import ANY, MagicMock, patch
+from zoneinfo import ZoneInfo
+
+import boto3
+from freezegun import freeze_time
+from mypy_boto3_ec2.client import EC2Client
+from mypy_boto3_ec2.literals import InstanceTypeType
+
+from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler.configuration.running_period import RunningPeriod
+from instance_scheduler.configuration.running_period_dict_element import (
+ RunningPeriodDictElement,
+)
+from instance_scheduler.handler.scheduling_request import SchedulingRequestHandler
+from instance_scheduler.schedulers.instance_states import InstanceStates
+from instance_scheduler.util.app_env import AppEnv
+from tests.context import MockLambdaContext
+from tests.integration.helpers.scheduling_context_builder import (
+ build_context,
+ build_scheduling_event,
+)
+from tests.integration.ops_metrics.conftest import solution_metrics_uuid
+
+medium: InstanceTypeType = "a1.medium"
+large: InstanceTypeType = "a1.large"
+
+will_start = InstanceSchedule(
+ name="start_instances",
+ periods=[
+ RunningPeriodDictElement(
+ period=RunningPeriod(name="stop", begintime=time(12, 0, 0))
+ )
+ ],
+)
+
+will_stop = InstanceSchedule(
+ name="stop_instances",
+ periods=[
+ RunningPeriodDictElement(
+ period=RunningPeriod(name="start", endtime=time(12, 0, 0))
+ )
+ ],
+ stop_new_instances=True,
+)
+
+will_resize_to_large = InstanceSchedule(
+ name="resize_instances",
+ periods=[
+ RunningPeriodDictElement(
+ period=RunningPeriod(
+ name="medium_window", begintime=time(6, 0, 0), endtime=time(12, 0, 0)
+ ),
+ instancetype=medium,
+ ),
+ RunningPeriodDictElement(
+ period=RunningPeriod(name="large_window", begintime=time(12, 0, 0)),
+ instancetype=large,
+ ),
+ ],
+)
+
+context = build_context(
+ current_dt=datetime(2023, 6, 12, 12, 0, 0, tzinfo=ZoneInfo("UTC")),
+ schedules={
+ "start_instances": will_start,
+ "stop_instances": will_stop,
+ "resize_instances": will_resize_to_large,
+ },
+)
+
+
+def create_test_instances(
+ count: int, instance_type: InstanceTypeType, schedule: InstanceSchedule
+) -> list[str]:
+ ec2_client: EC2Client = boto3.client("ec2")
+ instance_ids = new_ec2_instances_of_type(ec2_client, count, instance_type)
+ ec2_client.create_tags(
+ Resources=instance_ids, Tags=[{"Key": "Schedule", "Value": schedule.name}]
+ )
+
+ if schedule in [will_start, will_resize_to_large]:
+ ec2_client.stop_instances(InstanceIds=instance_ids)
+
+ return instance_ids
+
+
+def new_ec2_instances_of_type(
+ ec2_client: EC2Client, count: int, ec2_instance_type: InstanceTypeType
+) -> list[str]:
+ ami = "ami-0889ff9188674a22a"
+ create_response = ec2_client.run_instances(
+ ImageId=ami, MinCount=count, MaxCount=count, InstanceType=ec2_instance_type
+ )
+ instance_ids = [instance["InstanceId"] for instance in create_response["Instances"]]
+
+ return instance_ids
+
+
+def get_sent_scheduling_action_metric(metrics_endpoint: MagicMock) -> Any:
+ desired_metric: dict[str, Any] = {}
+ for call_args in metrics_endpoint.call_args_list:
+ json_payload = call_args[1]["data"]
+ sent_metric = json.loads(json_payload)
+
+ if sent_metric["Event_Name"] == "scheduling_action":
+ if desired_metric:
+ raise Exception("metric sent multiple times")
+ desired_metric = sent_metric
+
+ if not desired_metric:
+ raise Exception("metric not found")
+ return desired_metric
+
+
+@patch("instance_scheduler.schedulers.instance_scheduler.should_collect_metric")
+@freeze_time(datetime(2023, 6, 12, 12, 0, 0, tzinfo=ZoneInfo("UTC")))
+def test_scheduling_execution_sends_expected_actions_metric(
+ should_collect_metrics_func: MagicMock,
+ mock_metrics_endpoint: MagicMock,
+ moto_ec2: None,
+ ec2_instance_states: InstanceStates,
+ app_env: AppEnv,
+) -> None:
+ should_collect_metrics_func.return_value = True
+
+ create_test_instances(8, medium, will_start)
+ create_test_instances(6, large, will_start)
+ create_test_instances(4, medium, will_stop)
+ create_test_instances(2, large, will_stop)
+ create_test_instances(5, medium, will_resize_to_large) # instances already stopped
+
+ event = build_scheduling_event(context)
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ expected_metric = {
+ "TimeStamp": "2023-06-12 12:00:00",
+ "UUID": str(solution_metrics_uuid),
+ "Solution": app_env.solution_id,
+ "Version": app_env.solution_version,
+ "Event_Name": "scheduling_action",
+ "Context": {
+ "duration_seconds": ANY,
+ "actions": [
+ {
+ "action": "Started",
+ "instanceType": "a1.medium",
+ "instances": 8,
+ "service": "ec2",
+ },
+ {
+ "action": "Started",
+ "instanceType": "a1.large",
+ "instances": 11, # the 5 instances resized to a1.large were also started
+ "service": "ec2",
+ },
+ {
+ "action": "Stopped",
+ "instanceType": "a1.medium",
+ "instances": 4,
+ "service": "ec2",
+ },
+ {
+ "action": "Stopped",
+ "instanceType": "a1.large",
+ "instances": 2,
+ "service": "ec2",
+ },
+ {
+ "action": "Resized",
+ "instanceType": "a1.medium-a1.large",
+ "instances": 5,
+ "service": "ec2",
+ },
+ ],
+ },
+ }
+
+ sent_metric = get_sent_scheduling_action_metric(mock_metrics_endpoint)
+ assert sent_metric == expected_metric
+ assert sent_metric["Context"]["duration_seconds"] is not None
diff --git a/source/app/tests/integration/test_1_sided_schedules.py b/source/app/tests/integration/test_1_sided_schedules.py
new file mode 100644
index 00000000..9fd6aa75
--- /dev/null
+++ b/source/app/tests/integration/test_1_sided_schedules.py
@@ -0,0 +1,129 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import datetime
+
+import boto3
+from mypy_boto3_ec2.client import EC2Client
+
+from instance_scheduler.configuration.running_period import RunningPeriod
+from instance_scheduler.configuration.running_period_dict_element import (
+ RunningPeriodDictElement,
+)
+from instance_scheduler.handler.scheduling_request import SchedulingRequestHandler
+from instance_scheduler.schedulers.instance_states import InstanceStates
+from tests.context import MockLambdaContext
+from tests.integration.helpers.ec2_helpers import get_current_state
+from tests.integration.helpers.schedule_helpers import quick_time
+from tests.integration.helpers.scheduling_context_builder import (
+ build_context,
+ build_scheduling_event,
+ custom_schedule,
+)
+
+one_sided_start = RunningPeriodDictElement(
+ period=RunningPeriod(name="one-sided-start", begintime=datetime.time(10, 0, 0))
+)
+
+one_sided_stop = RunningPeriodDictElement(
+ period=RunningPeriod(name="one-sided-stop", endtime=datetime.time(20, 0, 0))
+)
+
+
+def test_enforced_1_sided_start_does_not_stop_instances_before_start_time(
+ ec2_instance: str, ec2_instance_states: InstanceStates
+) -> None:
+ # ----------------------------Event Definition--------------------------#
+ context = build_context(
+ current_dt=quick_time(5, 0, 0),
+ schedules=custom_schedule(periods=[one_sided_start], enforced=True),
+ )
+ event = build_scheduling_event(context)
+ # ----------------------------EC2 Instance-------------------------#
+ ec2_client: EC2Client = boto3.client("ec2")
+ ec2_client.start_instances(InstanceIds=[ec2_instance])
+
+ # ------------------------Last Desired State------------------------#
+ ec2_instance_states.set_instance_state(ec2_instance, "any")
+ ec2_instance_states.save()
+
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ # ---------------------validate result---------------------#
+ assert get_current_state(ec2_instance) == "running"
+
+
+def test_enforced_1_sided_stop_does_not_start_instances_before_stop_time(
+ ec2_instance: str, ec2_instance_states: InstanceStates
+) -> None:
+ # ----------------------------Event Definition--------------------------#
+ context = build_context(
+ current_dt=quick_time(5, 0, 0),
+ schedules=custom_schedule(periods=[one_sided_stop], enforced=True),
+ )
+ event = build_scheduling_event(context)
+ # ----------------------------EC2 Instance-------------------------#
+ ec2_client: EC2Client = boto3.client("ec2")
+ ec2_client.stop_instances(InstanceIds=[ec2_instance])
+
+ # ------------------------Last Desired State------------------------#
+ ec2_instance_states.set_instance_state(ec2_instance, "any")
+ ec2_instance_states.save()
+
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ # ---------------------validate result---------------------#
+ assert get_current_state(ec2_instance) == "stopped"
+
+
+def test_1_sided_stop_stops_at_stop_time(
+ ec2_instance: str, ec2_instance_states: InstanceStates
+) -> None:
+ # ----------------------------Event Definition--------------------------#
+ context = build_context(
+ current_dt=quick_time(20, 0, 0),
+ schedules=custom_schedule(periods=[one_sided_stop]),
+ )
+ event = build_scheduling_event(context)
+ # ----------------------------EC2 Instance-------------------------#
+ ec2_client: EC2Client = boto3.client("ec2")
+ ec2_client.start_instances(InstanceIds=[ec2_instance])
+
+ # ------------------------Last Desired State------------------------#
+ ec2_instance_states.set_instance_state(ec2_instance, "any")
+ ec2_instance_states.save()
+
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ # ---------------------validate result---------------------#
+ assert get_current_state(ec2_instance) == "stopped"
+
+
+def test_1_sided_start_starts_at_start_time(
+ ec2_instance: str, ec2_instance_states: InstanceStates
+) -> None:
+ # ----------------------------Event Definition--------------------------#
+ context = build_context(
+ current_dt=quick_time(10, 0, 0),
+ schedules=custom_schedule(periods=[one_sided_start]),
+ )
+ event = build_scheduling_event(context)
+ # ----------------------------EC2 Instance-------------------------#
+ ec2_client: EC2Client = boto3.client("ec2")
+ ec2_client.stop_instances(InstanceIds=[ec2_instance])
+
+ # ------------------------Last Desired State------------------------#
+ ec2_instance_states.set_instance_state(ec2_instance, "any")
+ ec2_instance_states.save()
+
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ # ---------------------validate result---------------------#
+ assert get_current_state(ec2_instance) == "running"
diff --git a/source/app/tests/integration/test_basic_ec2_scheduling.py b/source/app/tests/integration/test_basic_ec2_scheduling.py
new file mode 100644
index 00000000..9bc50bd0
--- /dev/null
+++ b/source/app/tests/integration/test_basic_ec2_scheduling.py
@@ -0,0 +1,276 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import datetime
+
+import boto3
+from mypy_boto3_ec2.client import EC2Client
+
+from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler.configuration.running_period import RunningPeriod
+from instance_scheduler.handler.scheduling_request import SchedulingRequestHandler
+from instance_scheduler.schedulers.instance_states import InstanceStates
+from tests.context import MockLambdaContext
+from tests.integration.helpers.ec2_helpers import get_current_state
+from tests.integration.helpers.schedule_helpers import quick_time
+from tests.integration.helpers.scheduling_context_builder import (
+ build_context,
+ build_scheduling_event,
+)
+
+
+def test_ec2_starts_at_beginning_of_period(
+ ec2_instance: str, ec2_instance_states: InstanceStates
+) -> None:
+ """
+ ----inputs----
+ schedule:
+ begintime = 10:00
+ endtime = 20:00
+ current time: 10:00
+ instance: stopped
+ last_desired_state: stopped
+
+ ----expect----
+ instance: running
+ """
+
+ # ----------------------------Event Definition--------------------------#
+ context = build_context(current_dt=quick_time(10, 0, 0))
+ event = build_scheduling_event(context)
+ # ----------------------------EC2 Instance-------------------------#
+ ec2_client: EC2Client = boto3.client("ec2")
+ ec2_client.stop_instances(InstanceIds=[ec2_instance])
+
+ # ------------------------Last Desired State------------------------#
+ ec2_instance_states.set_instance_state(ec2_instance, "stopped")
+ ec2_instance_states.save()
+
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ # ---------------------validate result---------------------#
+ assert get_current_state(ec2_instance) == "running"
+
+
+def test_ec2_stops_at_end_of_period(
+ ec2_instance: str, ec2_instance_states: InstanceStates
+) -> None:
+ """
+ ----inputs----
+ schedule:
+ begintime = 10:00
+ endtime = 20:00
+ current time: 20:00
+ instance: running
+ last_desired_state: running
+
+ ----expect----
+ instance: stopped
+ """
+ # ----------------------------Event Definition--------------------------#
+ context = build_context(current_dt=quick_time(20, 0, 0))
+ event = build_scheduling_event(context)
+ # ----------------------------EC2 Instance-------------------------#
+ ec2_client: EC2Client = boto3.client("ec2")
+ ec2_client.start_instances(InstanceIds=[ec2_instance])
+
+ # ------------------------Last Desired State------------------------#
+ ec2_instance_states.set_instance_state(ec2_instance, "running")
+ ec2_instance_states.save()
+
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ # ---------------------validate result---------------------#
+ assert get_current_state(ec2_instance) == "stopped"
+
+
+def test_ec2_does_not_start_in_middle_of_period(
+ ec2_instance: str, ec2_instance_states: InstanceStates
+) -> None: # default behavior should be to only start/stop at period boundaries
+ """
+ ----inputs----
+ schedule:
+ begintime = 10:00
+ endtime = 20:00
+ current time: 15:00
+ instance: stopped
+ last_desired_state: running
+
+ ----expect----
+ instance: stopped
+ """
+ # ----------------------------Event Definition--------------------------#
+ context = build_context(
+ current_dt=datetime.datetime.fromisoformat("2023-05-16T15:00:00+00:00"),
+ schedules={
+ "test-schedule": InstanceSchedule(
+ name="test-schedule",
+ periods=[
+ {
+ "period": RunningPeriod(
+ name="test-period",
+ begintime=datetime.time(10, 0, 0),
+ endtime=datetime.time(20, 0, 0),
+ )
+ }
+ ],
+ )
+ },
+ )
+
+ event = build_scheduling_event(context)
+ # ----------------------------EC2 Instance-------------------------#
+ ec2_client: EC2Client = boto3.client("ec2")
+ ec2_client.stop_instances(InstanceIds=[ec2_instance])
+
+ # ------------------------Last Desired State------------------------#
+ ec2_instance_states.set_instance_state(ec2_instance, "running")
+ ec2_instance_states.save()
+
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ # ---------------------validate result---------------------#
+ assert get_current_state(ec2_instance) == "stopped"
+
+
+def test_ec2_starts_when_inside_enforced_period(
+ ec2_instance: str, ec2_instance_states: InstanceStates
+) -> None:
+ """
+ ----inputs----
+ schedule:
+ begintime = 10:00
+ endtime = 20:00
+ enforced = true
+ current time: 15:00
+ instance: stopped
+ last_desired_state: running
+
+ ----expect----
+ instance: running
+ """
+ # ----------------------------Event Definition--------------------------#
+ context = build_context(
+ current_dt=quick_time(15, 0, 0),
+ schedules={
+ "test-schedule": InstanceSchedule(
+ name="test-schedule",
+ enforced=True,
+ periods=[
+ {
+ "period": RunningPeriod(
+ name="test-period",
+ begintime=datetime.time(10, 0, 0),
+ endtime=datetime.time(20, 0, 0),
+ )
+ }
+ ],
+ )
+ },
+ )
+ event = build_scheduling_event(context)
+ # ----------------------------EC2 Instance-------------------------#
+ ec2_client: EC2Client = boto3.client("ec2")
+ ec2_client.stop_instances(InstanceIds=[ec2_instance])
+
+ # ------------------------Last Desired State------------------------#
+ ec2_instance_states.set_instance_state(ec2_instance, "running")
+ ec2_instance_states.save()
+
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ # ---------------------validate result---------------------#
+ assert get_current_state(ec2_instance) == "running"
+
+
+def test_ec2_does_not_stop_outside_of_period(
+ ec2_instance: str, ec2_instance_states: InstanceStates
+) -> None: # default behavior should be to only start/stop at period boundaries
+ """
+ ----inputs----
+ schedule:
+ begintime = 10:00
+ endtime = 20:00
+ current time: 22:00
+ instance: running
+ last_desired_state: stopped
+
+ ----expect----
+ instance: running
+ """
+ # ----------------------------Event Definition--------------------------#
+ context = build_context(current_dt=quick_time(22, 0, 0))
+ event = build_scheduling_event(context)
+ # ----------------------------EC2 Instance-------------------------#
+ ec2_client: EC2Client = boto3.client("ec2")
+ ec2_client.start_instances(InstanceIds=[ec2_instance])
+
+ # ------------------------Last Desired State------------------------#
+ ec2_instance_states.set_instance_state(ec2_instance, "stopped")
+ ec2_instance_states.save()
+
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ # ---------------------validate result---------------------#
+ assert get_current_state(ec2_instance) == "running"
+
+
+def test_ec2_stops_when_outside_enforced_period(
+ ec2_instance: str, ec2_instance_states: InstanceStates
+) -> None:
+ """
+ inputs:
+ schedule:
+ begintime = 10:00
+ endtime = 20:00
+ enforced = true
+ current time: 22:00
+ instance: running
+ last_desired_state: stopped
+
+ output:
+ instance: stopped
+ """
+ # ----------------------------Event Definition--------------------------#
+ context = build_context(
+ current_dt=quick_time(22, 0, 0),
+ schedules={
+ "test-schedule": InstanceSchedule(
+ name="test-schedule",
+ enforced=True,
+ periods=[
+ {
+ "period": RunningPeriod(
+ name="test-period",
+ begintime=datetime.time(10, 0, 0),
+ endtime=datetime.time(20, 0, 0),
+ )
+ }
+ ],
+ )
+ },
+ )
+ event = build_scheduling_event(context)
+ # ----------------------------EC2 Instance-------------------------#
+ ec2_client: EC2Client = boto3.client("ec2")
+ ec2_client.start_instances(InstanceIds=[ec2_instance])
+
+ # ------------------------Last Desired State------------------------#
+ ec2_instance_states.set_instance_state(ec2_instance, "stopped")
+ ec2_instance_states.save()
+
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ # ---------------------validate result---------------------#
+ assert get_current_state(ec2_instance) == "stopped"
diff --git a/source/app/tests/integration/test_basic_rds_scheduling.py b/source/app/tests/integration/test_basic_rds_scheduling.py
new file mode 100644
index 00000000..3ef54780
--- /dev/null
+++ b/source/app/tests/integration/test_basic_rds_scheduling.py
@@ -0,0 +1,84 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+
+import boto3
+from mypy_boto3_rds import RDSClient
+
+from instance_scheduler.handler.scheduling_request import SchedulingRequestHandler
+from instance_scheduler.schedulers.instance_states import InstanceStates
+from tests.context import MockLambdaContext
+from tests.integration.helpers.rds_helpers import get_rds_instance_state
+from tests.integration.helpers.schedule_helpers import quick_time
+from tests.integration.helpers.scheduling_context_builder import (
+ build_context,
+ build_scheduling_event,
+)
+
+
+def test_rds_starts_at_beginning_of_period(
+ rds_instance: str, rds_instance_states: InstanceStates
+) -> None:
+ """
+ ----inputs----
+ schedule:
+ begintime = 10:00
+ endtime = 20:00
+ current time: 10:00
+ instance: stopped
+ last_desired_state: stopped
+
+ ----expect----
+ instance: available
+ """
+
+ # ----------------------------Event Definition--------------------------#
+ context = build_context(current_dt=quick_time(10, 0, 0), service="rds")
+ event = build_scheduling_event(context)
+ # ----------------------------RDS Instance-------------------------#
+ rds_client: RDSClient = boto3.client("rds")
+ rds_client.stop_db_instance(DBInstanceIdentifier=rds_instance)
+
+ # ------------------------Last Desired State------------------------#
+ rds_instance_states.set_instance_state(rds_instance, "stopped")
+ rds_instance_states.save()
+
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ # ---------------------validate result---------------------#
+ assert get_rds_instance_state(rds_instance) == "available"
+
+
+def test_rds_stops_at_end_of_period(
+ rds_instance: str, rds_instance_states: InstanceStates
+) -> None:
+ """
+ ----inputs----
+ schedule:
+ begintime = 10:00
+ endtime = 20:00
+ current time: 10:00
+ instance: stopped
+ last_desired_state: stopped
+
+ ----expect----
+ instance: available
+ """
+
+ # ----------------------------Event Definition--------------------------#
+ context = build_context(current_dt=quick_time(20, 0, 0), service="rds")
+ event = build_scheduling_event(context)
+ # ----------------------------RDS Instance-------------------------#
+ assert get_rds_instance_state(rds_instance) == "available" # defaults to available
+
+ # ------------------------Last Desired State------------------------#
+ rds_instance_states.set_instance_state(rds_instance, "running")
+ rds_instance_states.save()
+
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ # ---------------------validate result---------------------#
+ assert get_rds_instance_state(rds_instance) == "stopped"
diff --git a/source/app/tests/integration/test_basic_timezone_handling.py b/source/app/tests/integration/test_basic_timezone_handling.py
new file mode 100644
index 00000000..24b66d2d
--- /dev/null
+++ b/source/app/tests/integration/test_basic_timezone_handling.py
@@ -0,0 +1,109 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from datetime import datetime, time, timezone
+
+import boto3
+import pytest
+from mypy_boto3_ec2.client import EC2Client
+
+from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler.configuration.running_period import RunningPeriod
+from instance_scheduler.configuration.running_period_dict_element import (
+ RunningPeriodDictElement,
+)
+from instance_scheduler.handler.scheduling_request import SchedulingRequestHandler
+from instance_scheduler.schedulers.instance_states import InstanceStates
+from tests.context import MockLambdaContext
+from tests.integration.helpers.ec2_helpers import get_current_state
+from tests.integration.helpers.scheduling_context_builder import (
+ build_context,
+ build_scheduling_event,
+)
+
+stop_after_noon_period: RunningPeriodDictElement = {
+ "period": RunningPeriod(
+ name="test-period",
+ begintime=time(0, 0, 0),
+ endtime=time(12, 0, 0),
+ )
+}
+
+
+def tz_instance(tz_name: str) -> tuple[InstanceSchedule, str]:
+ ec2_client: EC2Client = boto3.client("ec2")
+ instance_id = new_ec2_instance(ec2_client)
+ ec2_client.create_tags(
+ Resources=[instance_id], Tags=[{"Key": "Schedule", "Value": tz_name}]
+ )
+
+ schedule = InstanceSchedule(
+ name=tz_name,
+ timezone=tz_name,
+ periods=[stop_after_noon_period],
+ enforced=True,
+ stop_new_instances=True,
+ )
+
+ return schedule, instance_id
+
+
+def new_ec2_instance(ec2_client: EC2Client) -> str:
+ ami = "ami-0889ff9188674a22a"
+ instance_id: str = ec2_client.run_instances(ImageId=ami, MinCount=1, MaxCount=1)[
+ "Instances"
+ ][0]["InstanceId"]
+ return instance_id
+
+
+def test_passing_tz_unaware_dt_to_scheduling_request_handler_throws_error() -> None:
+ context = build_context(current_dt=datetime(2023, 6, 19, 12, 0, 0))
+ event = build_scheduling_event(context)
+
+ with pytest.raises(ValueError):
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+
+def test_time_zones(moto_ec2: None, ec2_instance_states: InstanceStates) -> None:
+ # ----------------------------EC2 Instances-------------------------#
+ schedules: dict[str, InstanceSchedule] = {}
+ instances: dict[str, str] = {}
+
+ # all times related to 12:00 UTC
+ for tz in [
+ "Etc/GMT+12", # local time: 00:00
+ "Etc/GMT+10", # local time: 02:00
+ "Etc/GMT+5", # local time: 07:00
+ "Etc/GMT", # local time: 12:00
+ "Etc/GMT-5", # local time: 17:00
+ "Etc/GMT-10", # local time: 22:00
+ "Etc/GMT-13", # local time: 01:00
+ ]:
+ schedule, instance_id = tz_instance(tz)
+ schedules[tz] = schedule
+ instances[tz] = instance_id
+ ec2_instance_states.set_instance_state(instance_id, "running")
+
+ ec2_instance_states.save()
+ # ----------------------------Event Definition--------------------------#
+ context = build_context(
+ current_dt=datetime(2023, 6, 9, 12, 0, 0, tzinfo=timezone.utc),
+ schedules=schedules,
+ )
+ event = build_scheduling_event(context)
+
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ # ---------------------validate result---------------------#
+
+ # all instances between 0-12 should be running, all instances between 12-24 should be stopped
+
+ assert get_current_state(instances["Etc/GMT+12"]) == "running" # local time: 00:00
+ assert get_current_state(instances["Etc/GMT+10"]) == "running" # local time: 02:00
+ assert get_current_state(instances["Etc/GMT+5"]) == "running" # local time: 07:00
+ assert get_current_state(instances["Etc/GMT"]) == "stopped" # local time: 12:00
+ assert get_current_state(instances["Etc/GMT-5"]) == "stopped" # local time: 17:00
+ assert get_current_state(instances["Etc/GMT-10"]) == "stopped" # local time: 22:00
+ assert get_current_state(instances["Etc/GMT-13"]) == "running" # local time: 01:00
diff --git a/source/app/tests/integration/test_create_rds_snapshot_flag.py b/source/app/tests/integration/test_create_rds_snapshot_flag.py
new file mode 100644
index 00000000..0997bea7
--- /dev/null
+++ b/source/app/tests/integration/test_create_rds_snapshot_flag.py
@@ -0,0 +1,74 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+
+import boto3
+from mypy_boto3_rds import RDSClient
+from mypy_boto3_rds.type_defs import DBSnapshotMessageTypeDef
+
+from instance_scheduler.handler.scheduling_request import SchedulingRequestHandler
+from instance_scheduler.schedulers.instance_states import InstanceStates
+from tests.context import MockLambdaContext
+from tests.integration.helpers.rds_helpers import get_rds_instance_state
+from tests.integration.helpers.schedule_helpers import quick_time
+from tests.integration.helpers.scheduling_context_builder import (
+ build_context,
+ build_scheduling_event,
+)
+
+
+def test_rds_creates_snapshot_when_flag_enabled(
+ rds_instance: str, rds_instance_states: InstanceStates
+) -> None:
+ # ----------------------------Event Definition--------------------------#
+
+ context = build_context(
+ current_dt=quick_time(20, 0, 0), service="rds", create_rds_snapshot=True
+ )
+ event = build_scheduling_event(context)
+
+ # ----------------------------RDS Instance-------------------------#
+ # already setup and running
+ # ------------------------Last Desired State------------------------#
+ rds_instance_states.set_instance_state(rds_instance, "running")
+ rds_instance_states.save()
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ # ---------------------validate result---------------------#
+ assert (
+ get_rds_instance_state(rds_instance) == "stopped"
+ ) # ensure instance actually stopped
+ rds_client: RDSClient = boto3.client("rds")
+ result: DBSnapshotMessageTypeDef = rds_client.describe_db_snapshots(
+ DBInstanceIdentifier=rds_instance
+ )
+ assert len(result["DBSnapshots"]) == 1
+
+
+def test_rds_does_not_create_snapshot_when_flag_disabled(
+ rds_instance: str, rds_instance_states: InstanceStates
+) -> None:
+ # ----------------------------Event Definition--------------------------#
+ context = build_context(
+ current_dt=quick_time(20, 0, 0), service="rds", create_rds_snapshot=False
+ )
+ event = build_scheduling_event(context)
+ # ----------------------------RDS Instance-------------------------#
+ # already setup and running
+ # ------------------------Last Desired State------------------------#
+ rds_instance_states.set_instance_state(rds_instance, "running")
+ rds_instance_states.save()
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ # ---------------------validate result---------------------#
+ assert (
+ get_rds_instance_state(rds_instance) == "stopped"
+ ) # ensure instance actually stopped
+ rds_client: RDSClient = boto3.client("rds")
+ result: DBSnapshotMessageTypeDef = rds_client.describe_db_snapshots(
+ DBInstanceIdentifier=rds_instance
+ )
+ assert len(result["DBSnapshots"]) == 0
diff --git a/source/app/tests/integration/test_cross_account_scheduling.py b/source/app/tests/integration/test_cross_account_scheduling.py
new file mode 100644
index 00000000..ae440b7d
--- /dev/null
+++ b/source/app/tests/integration/test_cross_account_scheduling.py
@@ -0,0 +1,115 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import dataclasses
+
+from mypy_boto3_ec2 import EC2Client
+
+from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler.handler.scheduling_request import SchedulingRequestHandler
+from instance_scheduler.schedulers.instance_states import InstanceStates
+from instance_scheduler.util.app_env import AppEnv
+from tests.context import MockLambdaContext
+from tests.integration.helpers.boto_client_helpers import client_in_account_region
+from tests.integration.helpers.ec2_helpers import (
+ create_ec2_instances,
+ get_current_state,
+)
+from tests.integration.helpers.schedule_helpers import quick_time
+from tests.integration.helpers.scheduling_context_builder import (
+ build_context,
+ build_scheduling_event,
+ default_test_schedule,
+)
+
+
+class LocalizedTestInstance:
+ def __init__(
+ self,
+ schedule: InstanceSchedule,
+ account: str = "123456789012",
+ region: str = "us-east-1",
+ ) -> None:
+ self.client: EC2Client = client_in_account_region("ec2", account, region)
+ (self.instance_id,) = create_ec2_instances(1, schedule, account, region)
+
+ def current_state(self) -> str:
+ return get_current_state(self.instance_id, self.client)
+
+
+def test_cross_account_cross_region_ec2_scheduling_starts_and_stops_instance(
+ moto_ec2: None, ec2_instance_states: InstanceStates, app_env: AppEnv
+) -> None:
+ account = "222233334444"
+ region = "us-west-2"
+ (ec2_instance,) = create_ec2_instances(1, default_test_schedule(), account, region)
+
+ # ----------------------------Event Definition--------------------------#
+ context = build_context(
+ current_dt=quick_time(10, 0, 0),
+ region=region,
+ schedule_lambda_account=False,
+ account_id=account,
+ )
+ event = build_scheduling_event(context)
+ # ----------------------------EC2 Instance-------------------------#
+ ec2_client: EC2Client = client_in_account_region("ec2", account, region)
+ ec2_client.stop_instances(InstanceIds=[ec2_instance])
+
+ # ------------------------Last Desired State------------------------#
+ ec2_instance_states.load(account, region)
+ ec2_instance_states.set_instance_state(ec2_instance, "stopped")
+ ec2_instance_states.save()
+
+ # ---------------------start---------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ assert get_current_state(ec2_instance, ec2_client) == "running"
+
+ # ---------------------stop---------------------#
+ context = dataclasses.replace(context, current_dt=quick_time(20, 0, 0))
+ event = build_scheduling_event(context)
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ assert get_current_state(ec2_instance, ec2_client) == "stopped"
+
+
+def test_cross_account_scheduling_does_not_schedule_other_instances(
+ moto_ec2: None, ec2_instance_states: InstanceStates, app_env: AppEnv
+) -> None:
+ target_account = "222233334444"
+ target_region = "us-west-2"
+
+ schedule = InstanceSchedule(
+ name="force-stop",
+ enforced=True,
+ override_status="stopped",
+ stop_new_instances=True,
+ )
+
+ context = build_context(
+ current_dt=quick_time(10, 0, 0),
+ region=target_region,
+ schedule_lambda_account=False,
+ account_id=target_account,
+ schedules={schedule.name: schedule},
+ )
+
+ event = build_scheduling_event(context)
+
+ target_instance = LocalizedTestInstance(
+ schedule, account=target_account, region=target_region
+ )
+ bad_instances = [
+ LocalizedTestInstance(schedule, account=target_account),
+ LocalizedTestInstance(schedule, region=target_region),
+ LocalizedTestInstance(schedule),
+ ]
+
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ assert target_instance.current_state() == "stopped"
+ for bad_instance in bad_instances:
+ assert bad_instance.current_state() == "running"
diff --git a/source/app/tests/integration/test_ec2_instance_tagging.py b/source/app/tests/integration/test_ec2_instance_tagging.py
new file mode 100644
index 00000000..f5b72472
--- /dev/null
+++ b/source/app/tests/integration/test_ec2_instance_tagging.py
@@ -0,0 +1,163 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import dataclasses
+from datetime import datetime, timezone
+
+import boto3
+from freezegun.api import freeze_time
+from mypy_boto3_ec2.client import EC2Client
+
+from instance_scheduler.configuration.scheduling_context import TagTemplate
+from instance_scheduler.handler.scheduling_request import SchedulingRequestHandler
+from instance_scheduler.schedulers.instance_states import InstanceStates
+from instance_scheduler.util.app_env import AppEnv
+from tests.context import MockLambdaContext
+from tests.integration.helpers.ec2_helpers import get_tags
+from tests.integration.helpers.schedule_helpers import quick_time
+from tests.integration.helpers.scheduling_context_builder import (
+ build_context,
+ build_scheduling_event,
+)
+
+
+@freeze_time("2023-06-12 5:00:00")
+def test_ec2_start_tag_is_applied_on_start(
+ app_env: AppEnv, ec2_instance: str, ec2_instance_states: InstanceStates
+) -> None:
+ """
+ test that the start tag is applied with the correct substitutions
+ note - the correct time substitution is actual time (from freeze_time) NOT schedule time (current_dt)
+ """
+ context = build_context(
+ current_dt=datetime(2023, 6, 12, 10, 0, 0, tzinfo=timezone.utc),
+ started_tags=[
+ {
+ "Key": "action",
+ "Value": "started by {scheduler} on {year}/{month}/{day} at {hour}:{minute} {timezone}",
+ }
+ ],
+ )
+ event = build_scheduling_event(context)
+
+ # ----------------------------EC2 Instance-------------------------#
+ ec2_client: EC2Client = boto3.client("ec2")
+ ec2_client.stop_instances(InstanceIds=[ec2_instance])
+
+ # ------------------------Last Desired State------------------------#
+ ec2_instance_states.set_instance_state(ec2_instance, "stopped")
+ ec2_instance_states.save()
+
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ # ---------------------validate result---------------------#
+
+ tags = get_tags(ec2_instance)
+
+ assert tags.__contains__(
+ {
+ "Key": "action",
+ "Value": f"started by {app_env.stack_name} on 2023/06/12 at 05:00 UTC",
+ }
+ )
+
+
+@freeze_time("2023-06-12 15:00:00")
+def test_ec2_stop_tag_is_applied_on_stop(
+ app_env: AppEnv, ec2_instance: str, ec2_instance_states: InstanceStates
+) -> None:
+ """
+ test that the stop tag is applied with the correct substitutions
+ note - the correct time substitution is actual time (from freeze_time) NOT schedule time (current_dt)
+ """
+ context = build_context(
+ current_dt=datetime(2023, 6, 12, 20, 0, 0, tzinfo=timezone.utc),
+ stopped_tags=[
+ {
+ "Key": "action",
+ "Value": "stopped by {scheduler} on {year}/{month}/{day} at {hour}:{minute} {timezone}",
+ }
+ ],
+ )
+ event = build_scheduling_event(context)
+
+ # ----------------------------EC2 Instance-------------------------#
+ ec2_client: EC2Client = boto3.client("ec2")
+ ec2_client.start_instances(InstanceIds=[ec2_instance])
+
+ # ------------------------Last Desired State------------------------#
+ ec2_instance_states.set_instance_state(ec2_instance, "running")
+ ec2_instance_states.save()
+
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ # ---------------------validate result---------------------#
+
+ tags = get_tags(ec2_instance)
+
+ assert tags.__contains__(
+ {
+ "Key": "action",
+ "Value": f"stopped by {app_env.stack_name} on 2023/06/12 at 15:00 UTC",
+ }
+ )
+
+
+def test_ec2_start_stop_tags_are_mutually_exclusive(
+ ec2_instance: str, ec2_instance_states: InstanceStates
+) -> None:
+ """when start tags are applied, stop tags should be removed and vice-versa"""
+ started_tag1: TagTemplate = {"Key": "started1", "Value": "start1"}
+ started_tag2: TagTemplate = {"Key": "started2", "Value": "start2"}
+ stopped_tag1: TagTemplate = {"Key": "stopped1", "Value": "stop1"}
+ stopped_tag2: TagTemplate = {"Key": "stopped2", "Value": "stop2"}
+
+ context = build_context(
+ current_dt=quick_time(10, 0, 0),
+ started_tags=[started_tag1, started_tag2],
+ stopped_tags=[stopped_tag1, stopped_tag2],
+ )
+ event = build_scheduling_event(context)
+
+ # ----------------------------initial setup-------------------------#
+ ec2_client: EC2Client = boto3.client("ec2")
+ ec2_client.stop_instances(InstanceIds=[ec2_instance])
+ ec2_instance_states.set_instance_state(ec2_instance, "stopped")
+ ec2_instance_states.save()
+
+ # ------------------------first start------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ instance_tags = get_tags(ec2_instance)
+ assert started_tag1 in instance_tags
+ assert started_tag2 in instance_tags
+ assert stopped_tag1 not in instance_tags
+ assert stopped_tag2 not in instance_tags
+
+ # -------------------stop------------------------#
+ context = dataclasses.replace(context, current_dt=quick_time(20, 0, 0))
+ event = build_scheduling_event(context)
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ instance_tags = get_tags(ec2_instance)
+ assert started_tag1 not in instance_tags
+ assert started_tag2 not in instance_tags
+ assert stopped_tag1 in instance_tags
+ assert stopped_tag2 in instance_tags
+
+ # ---------------------start again---------------------#
+ context = dataclasses.replace(context, current_dt=quick_time(10, 0, 0))
+ event = build_scheduling_event(context)
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ instance_tags = get_tags(ec2_instance)
+ assert started_tag1 in instance_tags
+ assert started_tag2 in instance_tags
+ assert stopped_tag1 not in instance_tags
+ assert stopped_tag2 not in instance_tags
diff --git a/source/app/tests/integration/test_lambda_schedule_encoding_limits.py b/source/app/tests/integration/test_lambda_schedule_encoding_limits.py
new file mode 100644
index 00000000..eba97b25
--- /dev/null
+++ b/source/app/tests/integration/test_lambda_schedule_encoding_limits.py
@@ -0,0 +1,100 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+"""
+tests for schedule encoding limits of lambda
+
+by default, all configured schedules are encoded into the event sent to the scheduling_request handler. However,
+if a customer has too many schedules this event can exceed the maximum payload size for a Lambda request.
+
+In this scenario the schedules will be omitted from the event, and instead need to be refetched from dynamodb
+"""
+import datetime
+import json
+from unittest.mock import MagicMock, patch
+
+from instance_scheduler import configuration
+from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler.configuration.running_period import RunningPeriod
+from instance_scheduler.configuration.scheduling_context import SchedulingContext
+from instance_scheduler.handler import scheduling_orchestrator
+from instance_scheduler.handler.scheduling_orchestrator import (
+ OrchestrationRequest,
+ SchedulingOrchestratorHandler,
+)
+from instance_scheduler.handler.scheduling_request import (
+ SchedulerRequest,
+ SchedulingRequestHandler,
+)
+from tests.context import MockLambdaContext
+from tests.integration.helpers.global_config import build_global_config
+from tests.integration.helpers.schedule_helpers import quick_time
+from tests.integration.helpers.scheduling_context_builder import build_context
+
+global_config = build_global_config(
+ schedules={
+ "global-schedule": InstanceSchedule(
+ name="global-schedule",
+ periods=[
+ {
+ "period": RunningPeriod(
+ name="global-period",
+ begintime=datetime.time(10, 0, 0),
+ endtime=datetime.time(20, 0, 0),
+ )
+ }
+ ],
+ )
+ },
+)
+
+mock_event_bridge_event: OrchestrationRequest = {
+ "scheduled_action": "run_orchestrator",
+}
+
+
+def build_stripped_event(context: SchedulingContext) -> SchedulerRequest:
+ payload = context.to_dict()
+ scheduling_orchestrator.strip_schedules_and_periods(payload)
+ return {
+ "action": "scheduler:run",
+ "configuration": payload,
+ "dispatch_time": "dispatchTime",
+ }
+
+
+@patch.object(SchedulingOrchestratorHandler, "configuration", global_config)
+@patch.object(SchedulingOrchestratorHandler, "lambda_client")
+def test_strips_schedules_when_payload_is_too_large(lambda_client: MagicMock) -> None:
+ scheduling_orchestrator.LAMBDA_PAYLOAD_CAPACITY_BYTES = 0
+ with patch.object(lambda_client, "invoke") as invoke_func:
+ cloudwatch_handler = SchedulingOrchestratorHandler(
+ event=mock_event_bridge_event, context=MockLambdaContext()
+ )
+ cloudwatch_handler.handle_request()
+
+ assert invoke_func.call_count == 1
+ payload = invoke_func.call_args[1]["Payload"]
+ content = json.loads(payload)
+ assert content["configuration"]["schedules"] == {}
+ assert content["configuration"]["periods"] == {}
+
+
+@patch.object(configuration, "get_global_configuration")
+@patch("instance_scheduler.handler.scheduling_request.InstanceScheduler")
+def test_scheduling_request_handler_reloads_schedules_when_not_provided(
+ mock_scheduler: MagicMock, fetch_global_config_func: MagicMock
+) -> None:
+ # setup
+ fetch_global_config_func.return_value = global_config
+ context = build_context(current_dt=quick_time(10, 0, 0))
+ event = build_stripped_event(context)
+
+ # run handler
+ scheduling_handler = SchedulingRequestHandler(event, MockLambdaContext())
+ scheduling_handler.handle_request()
+
+ # assert that the schedule that gets passed to instance_scheduler is global-schedule, not stripped-schedule
+ assert mock_scheduler.call_count == 1
+ schedules_passed_to_scheduler = mock_scheduler.call_args.args[1].schedules
+ assert "global-schedule" in schedules_passed_to_scheduler
+ assert "stripped-schedule" not in schedules_passed_to_scheduler
diff --git a/source/app/tests/integration/test_rds_cluster_instance.py b/source/app/tests/integration/test_rds_cluster_instance.py
new file mode 100644
index 00000000..f33af900
--- /dev/null
+++ b/source/app/tests/integration/test_rds_cluster_instance.py
@@ -0,0 +1,63 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from typing import TYPE_CHECKING
+
+import boto3
+
+from instance_scheduler.handler.scheduling_request import SchedulingRequestHandler
+from instance_scheduler.schedulers.instance_states import InstanceStates
+from tests.context import MockLambdaContext
+from tests.integration.helpers.rds_helpers import (
+ get_rds_cluster_state,
+ get_rds_instance_state,
+)
+from tests.integration.helpers.schedule_helpers import quick_time
+from tests.integration.helpers.scheduling_context_builder import (
+ build_context,
+ build_scheduling_event,
+)
+
+if TYPE_CHECKING:
+ from mypy_boto3_rds.client import RDSClient
+else:
+ RDSClient = object
+
+
+def test_rds_cluster_instance_not_scheduled(
+ rds_cluster: str, rds_instance_states: InstanceStates
+) -> None:
+ """Instances part of an aurora cluster should not be scheduled, even if tagged"""
+ context = build_context(
+ current_dt=quick_time(10, 0, 0), schedule_clusters=False, service="rds"
+ )
+ event = build_scheduling_event(context)
+
+ rds_client: RDSClient = boto3.client("rds")
+
+ cluster = rds_client.describe_db_clusters(DBClusterIdentifier=rds_cluster)
+ instances = [instance for instance in cluster["DBClusters"][0]["DBClusterMembers"]]
+
+ assert instances
+ for instance in instances:
+ instance_description = rds_client.describe_db_instances(
+ DBInstanceIdentifier=instance["DBInstanceIdentifier"]
+ )
+ arn = instance_description["DBInstances"][0]["DBInstanceArn"]
+ rds_client.add_tags_to_resource(
+ ResourceName=arn, Tags=[{"Key": "Schedule", "Value": "test-schedule"}]
+ )
+ rds_client.stop_db_instance(
+ DBInstanceIdentifier=instance["DBInstanceIdentifier"]
+ )
+
+ rds_client.stop_db_cluster(DBClusterIdentifier=rds_cluster)
+
+ rds_instance_states.set_instance_state(rds_cluster, "stopped")
+ rds_instance_states.save()
+
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ assert get_rds_cluster_state(rds_cluster) == "stopped"
+ for instance in instances:
+ assert get_rds_instance_state(instance["DBInstanceIdentifier"]) == "stopped"
diff --git a/source/app/tests/integration/test_rds_cluster_scheduling.py b/source/app/tests/integration/test_rds_cluster_scheduling.py
new file mode 100644
index 00000000..da8829b3
--- /dev/null
+++ b/source/app/tests/integration/test_rds_cluster_scheduling.py
@@ -0,0 +1,53 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import boto3
+from mypy_boto3_rds import RDSClient
+
+from instance_scheduler.handler.scheduling_request import SchedulingRequestHandler
+from instance_scheduler.schedulers.instance_states import InstanceStates
+from tests.context import MockLambdaContext
+from tests.integration.helpers.rds_helpers import get_rds_cluster_state
+from tests.integration.helpers.schedule_helpers import quick_time
+from tests.integration.helpers.scheduling_context_builder import (
+ build_context,
+ build_scheduling_event,
+)
+
+
+def test_rds_cluster_starts_at_beginning_of_period(
+ rds_cluster: str, rds_instance_states: InstanceStates
+) -> None:
+ context = build_context(
+ current_dt=quick_time(10, 0, 0), schedule_clusters=True, service="rds"
+ )
+ event = build_scheduling_event(context)
+
+ rds_client: RDSClient = boto3.client("rds")
+ rds_client.stop_db_cluster(DBClusterIdentifier=rds_cluster)
+
+ rds_instance_states.set_instance_state(rds_cluster, "stopped")
+ rds_instance_states.save()
+
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ assert get_rds_cluster_state(rds_cluster) == "available"
+
+
+def test_rds_cluster_stops_at_end_of_period(
+ rds_cluster: str, rds_instance_states: InstanceStates
+) -> None:
+ context = build_context(
+ current_dt=quick_time(20, 0, 0), schedule_clusters=True, service="rds"
+ )
+ event = build_scheduling_event(context)
+
+ assert get_rds_cluster_state(rds_cluster) == "available"
+
+ rds_instance_states.set_instance_state(rds_cluster, "running")
+ rds_instance_states.save()
+
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ assert get_rds_cluster_state(rds_cluster) == "stopped"
diff --git a/source/app/tests/integration/test_resize.py b/source/app/tests/integration/test_resize.py
new file mode 100644
index 00000000..16cc69fb
--- /dev/null
+++ b/source/app/tests/integration/test_resize.py
@@ -0,0 +1,119 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import datetime
+
+import boto3
+from mypy_boto3_ec2.client import EC2Client
+
+from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler.configuration.running_period import RunningPeriod
+from instance_scheduler.handler.scheduling_request import SchedulingRequestHandler
+from instance_scheduler.schedulers.instance_states import InstanceStates
+from tests.context import MockLambdaContext
+from tests.integration.helpers.ec2_helpers import get_current_state
+from tests.integration.helpers.schedule_helpers import quick_time
+from tests.integration.helpers.scheduling_context_builder import (
+ build_context,
+ build_scheduling_event,
+)
+
+
+def test_stopped_instance_resized(
+ ec2_instance: str, ec2_instance_states: InstanceStates
+) -> None:
+ ec2_client: EC2Client = boto3.client("ec2")
+ ec2_client.stop_instances(InstanceIds=[ec2_instance])
+ ec2_client.modify_instance_attribute(
+ InstanceId=ec2_instance, InstanceType={"Value": "c6g.medium"}
+ )
+
+ desired_instance_type = "c6g.2xlarge"
+
+ context = build_context(
+ current_dt=quick_time(10, 0, 0),
+ schedules={
+ "test-schedule": InstanceSchedule(
+ name="test-schedule",
+ periods=[
+ {
+ "period": RunningPeriod(
+ name="test-period",
+ begintime=datetime.time(10, 0, 0),
+ endtime=datetime.time(20, 0, 0),
+ ),
+ "instancetype": desired_instance_type,
+ }
+ ],
+ )
+ },
+ )
+
+ event = build_scheduling_event(context)
+
+ ec2_instance_states.set_instance_state(ec2_instance, "stopped")
+ ec2_instance_states.save()
+
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ assert get_current_state(ec2_instance) == "running"
+ assert (
+ ec2_client.describe_instances(InstanceIds=[ec2_instance])["Reservations"][0][
+ "Instances"
+ ][0]["InstanceType"]
+ == desired_instance_type
+ )
+
+
+def test_running_instance_is_stopped_for_resize(
+ ec2_instance: str, ec2_instance_states: InstanceStates
+) -> None:
+ ec2_client: EC2Client = boto3.client("ec2")
+ ec2_client.stop_instances(InstanceIds=[ec2_instance])
+ ec2_client.modify_instance_attribute(
+ InstanceId=ec2_instance, InstanceType={"Value": "c6g.medium"}
+ )
+ ec2_client.start_instances(InstanceIds=[ec2_instance])
+
+ desired_instance_type = "c6g.2xlarge"
+
+ context = build_context(
+ current_dt=quick_time(15, 0, 0),
+ schedules={
+ "test-schedule": InstanceSchedule(
+ name="test-schedule",
+ periods=[
+ {
+ "period": RunningPeriod(
+ name="test-period",
+ begintime=datetime.time(10, 0, 0),
+ endtime=datetime.time(20, 0, 0),
+ ),
+ "instancetype": desired_instance_type,
+ }
+ ],
+ )
+ },
+ )
+
+ event = build_scheduling_event(context)
+
+ ec2_instance_states.set_instance_state(ec2_instance, "running")
+ ec2_instance_states.save()
+
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ ec2_instance_states.load(account="123456789012", region="us-east-1")
+ assert get_current_state(ec2_instance) == "stopped"
+
+ # rerun handler to confirm the resize would be finished next interval
+
+ handler.handle_request()
+ assert get_current_state(ec2_instance) == "running"
+ assert (
+ ec2_client.describe_instances(InstanceIds=[ec2_instance])["Reservations"][0][
+ "Instances"
+ ][0]["InstanceType"]
+ == desired_instance_type
+ )
diff --git a/source/app/tests/integration/test_retain_running_flag.py b/source/app/tests/integration/test_retain_running_flag.py
new file mode 100644
index 00000000..6dc4cef5
--- /dev/null
+++ b/source/app/tests/integration/test_retain_running_flag.py
@@ -0,0 +1,170 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import datetime
+from typing import Any
+
+import boto3
+from mypy_boto3_ec2.client import EC2Client
+
+from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler.configuration.running_period import RunningPeriod
+from instance_scheduler.handler.scheduling_request import SchedulingRequestHandler
+from instance_scheduler.schedulers.instance_states import InstanceStates
+from tests.context import MockLambdaContext
+from tests.integration.helpers.ec2_helpers import get_current_state
+from tests.integration.helpers.schedule_helpers import at_time
+from tests.integration.helpers.scheduling_context_builder import (
+ build_context,
+ build_scheduling_event,
+)
+
+
+def schedule_event_at_time(
+ time: datetime.time, retain_running_flag: bool = True
+) -> Any:
+ """
+ helper method for quickly building a scheduling event with the following:
+ begintime: 10:00
+ endtime: 20:00
+ retain_running: true
+ """
+ context = build_context(
+ current_dt=at_time(time),
+ schedules={
+ "test-schedule": InstanceSchedule(
+ name="test-schedule",
+ retain_running=retain_running_flag,
+ periods=[
+ {
+ "period": RunningPeriod(
+ name="test-period",
+ begintime=datetime.time(10, 0, 0),
+ endtime=datetime.time(20, 0, 0),
+ )
+ }
+ ],
+ )
+ },
+ )
+
+ event = build_scheduling_event(context)
+
+ return event
+
+
+def setup_retain_running_scenario(
+ ec2_instance: str,
+ ec2_instance_states: InstanceStates,
+ retain_running_flag: bool = True,
+) -> None:
+ """
+ The retain_running flag comes into effect when an instance is manually started by
+ a customer outside of normal schedule control
+
+ this method simulates the initial prerequisites for a schedule to enter this scenario
+
+ scenario simulated:
+ - running period of 10-20,
+ - instance was stopped under normal circumstances (last desired state = stopped),
+ - customer started instance manually at some point during the last off period and is discovered as already
+ running when the scheduler tries to start the instance at the beginning of the period (10)
+
+ this should cause the instance to be identified as having been started manually and will tag it with
+ the retain_running flag
+ """
+ # ----------------------------Event Definition--------------------------#
+ event = schedule_event_at_time(
+ datetime.time(10, 0, 0), retain_running_flag=retain_running_flag
+ )
+ # ----------------------------EC2 Instance-------------------------#
+ ec2_client: EC2Client = boto3.client("ec2")
+ ec2_client.start_instances(InstanceIds=[ec2_instance])
+
+ # ------------------------Last Desired State------------------------#
+ ec2_instance_states.set_instance_state(ec2_instance, "stopped")
+ ec2_instance_states.save()
+
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+
+def test_instance_is_stopped_at_end_of_period_when_flag_is_not_set(
+ ec2_instance: str, ec2_instance_states: InstanceStates
+) -> None:
+ # ----------------------------Setup--------------------------#
+ setup_retain_running_scenario(
+ ec2_instance, ec2_instance_states, retain_running_flag=False
+ )
+
+ # Ec2 instance and instance states should already be setup now
+
+ # ----------------------------Event Definition--------------------------#
+ event = schedule_event_at_time(datetime.time(20, 0, 0), retain_running_flag=False)
+
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ # ---------------------validate result---------------------#
+ assert get_current_state(ec2_instance) == "stopped"
+
+
+def test_instance_is_not_stopped_at_end_of_period_when_flag_is_set(
+ ec2_instance: str, ec2_instance_states: InstanceStates
+) -> None:
+ # ----------------------------Setup--------------------------#
+ setup_retain_running_scenario(
+ ec2_instance, ec2_instance_states, retain_running_flag=True
+ )
+
+ # Ec2 instance and instance states should already be setup now
+
+ # ----------------------------Event Definition--------------------------#
+ event = schedule_event_at_time(datetime.time(20, 0, 0))
+
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ # ---------------------validate result---------------------#
+ assert get_current_state(ec2_instance) == "running"
+
+
+def test_retain_running_behavior_over_multiple_scheduling_cycles(
+ ec2_instance: str, ec2_instance_states: InstanceStates
+) -> None:
+ # ----------------------------Setup--------------------------#
+ setup_retain_running_scenario(
+ ec2_instance, ec2_instance_states, retain_running_flag=True
+ )
+
+ for i in range(1, 3):
+ # ----------------------------Period Start--------------------------#
+ event = schedule_event_at_time(datetime.time(10, 0, 0))
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ assert get_current_state(ec2_instance) == "running"
+
+ # ----------------------------Period End----------------------------#
+ event = schedule_event_at_time(datetime.time(20, 0, 0))
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ assert get_current_state(ec2_instance) == "running"
+
+ # disable retain-running flag to confirm running behavior was actually because of the flag
+ # ----------------------------Period Start--------------------------#
+ event = schedule_event_at_time(datetime.time(10, 0, 0), retain_running_flag=False)
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ assert get_current_state(ec2_instance) == "running"
+
+ # ----------------------------Period End----------------------------#
+ event = schedule_event_at_time(datetime.time(20, 0, 0), retain_running_flag=False)
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ assert get_current_state(ec2_instance) == "stopped"
diff --git a/source/app/tests/integration/test_stack_update.py b/source/app/tests/integration/test_stack_update.py
new file mode 100644
index 00000000..f02ba080
--- /dev/null
+++ b/source/app/tests/integration/test_stack_update.py
@@ -0,0 +1,122 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import json
+from typing import TYPE_CHECKING
+from unittest.mock import MagicMock, patch
+
+import boto3
+from aws_lambda_powertools.utilities.typing import LambdaContext
+
+from instance_scheduler.handler.config_resource import (
+ SchedulerSetupHandler,
+ ServiceSetupResourceProperties,
+)
+from instance_scheduler.util.app_env import AppEnv
+from instance_scheduler.util.custom_resource import CustomResourceRequest
+
+if TYPE_CHECKING:
+ from mypy_boto3_dynamodb.client import DynamoDBClient
+else:
+ DynamoDBClient = object
+
+
+@patch("custom_resource.requests")
+class CustomResourceLambdaContext(LambdaContext):
+ def __init__(self) -> None:
+ LambdaContext.__init__(self)
+ self._log_group_name = "my-log-group"
+
+ @staticmethod
+ def get_remaining_time_in_millis() -> int:
+ return 1000 * 60 * 15
+
+
+def resource_properties(
+ org_id: str, config_table_name: str
+) -> ServiceSetupResourceProperties:
+ return ServiceSetupResourceProperties(
+ ServiceToken="lambda-arn",
+ timeout=120,
+ config_table=config_table_name,
+ tagname="Schedule",
+ default_timezone="UTC",
+ use_metrics="False",
+ scheduled_services=["ec2"],
+ schedule_clusters="False",
+ create_rds_snapshot="False",
+ regions=["us-east-1"],
+ remote_account_ids=[org_id],
+ namespace="test",
+ aws_partition="aws",
+ scheduler_role_name="scheduler-role",
+ schedule_lambda_account="False",
+ trace="False",
+ enable_ssm_maintenance_windows="False",
+ log_retention_days=30,
+ started_tags="",
+ stopped_tags="",
+ stack_version="v9.9.9",
+ use_aws_organizations="True",
+ )
+
+
+@patch("requests.put")
+def test_remote_account_ids_retained(
+ mock_requests: MagicMock,
+ moto_dynamodb: None,
+ app_env: AppEnv,
+ config_table: None,
+) -> None:
+ accounts = ["111111111111", "222222222222"]
+
+ config_table_name = app_env.config_table_name
+ org_id = "o-0000000000"
+ ddb: DynamoDBClient = boto3.client("dynamodb")
+ ddb.put_item(
+ TableName=config_table_name,
+ Item={
+ "type": {"S": "config"},
+ "name": {"S": "scheduler"},
+ "aws_partition": {"S": "aws"},
+ "create_rds_snapshot": {"BOOL": False},
+ "default_timezone": {"S": "UTC"},
+ "enable_ssm_maintenance_windows": {"BOOL": False},
+ "namespace": {"S": "test"},
+ "organization_id": {"S": org_id},
+ "regions": {"SS": ["us-east-1"]},
+ "remote_account_ids": {"SS": accounts},
+ "scheduled_services": {"SS": ["ec2"]},
+ "scheduler_role_name": {"S": "scheduler-role"},
+ "schedule_clusters": {"BOOL": False},
+ "schedule_lambda_account": {"BOOL": True},
+ "started_tags": {"S": ""},
+ "tagname": {"S": "Schedule"},
+ "trace": {"BOOL": False},
+ "use_metrics": {"BOOL": False},
+ },
+ )
+
+ event = CustomResourceRequest[ServiceSetupResourceProperties](
+ ServiceToken="",
+ RequestType="Update",
+ ResponseURL="",
+ StackId="arn:aws:cloudformation:us-east-1:111111111111:stack/my-stack/00000000-0000-0000-0000-000000000000",
+ RequestId="",
+ ResourceType="Custom::ServiceSetup",
+ LogicalResourceId="",
+ PhysicalResourceId="",
+ ResourceProperties=resource_properties(org_id, config_table_name),
+ OldResourceProperties=resource_properties(org_id, config_table_name),
+ )
+
+ SchedulerSetupHandler(event, CustomResourceLambdaContext()).handle_request()
+
+ mock_requests.assert_called_once()
+ assert json.loads(mock_requests.call_args.kwargs["data"])["Status"] == "SUCCESS"
+
+ config = ddb.get_item(
+ TableName=config_table_name,
+ Key={"type": {"S": "config"}, "name": {"S": "scheduler"}},
+ )["Item"]
+
+ assert set(config["remote_account_ids"]["SS"]) == set(accounts)
diff --git a/source/app/tests/integration/test_stop_new_instances_flag.py b/source/app/tests/integration/test_stop_new_instances_flag.py
new file mode 100644
index 00000000..ac02d297
--- /dev/null
+++ b/source/app/tests/integration/test_stop_new_instances_flag.py
@@ -0,0 +1,225 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import datetime
+
+import boto3
+from mypy_boto3_ec2.client import EC2Client
+
+from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler.configuration.running_period import RunningPeriod
+from instance_scheduler.handler.scheduling_request import SchedulingRequestHandler
+from instance_scheduler.schedulers.instance_states import InstanceStates
+from tests.context import MockLambdaContext
+from tests.integration.helpers.ec2_helpers import get_current_state
+from tests.integration.helpers.schedule_helpers import quick_time
+from tests.integration.helpers.scheduling_context_builder import (
+ build_context,
+ build_scheduling_event,
+)
+
+
+def test_new_instance_stops_when_outside_period_and_flag_is_set(
+ ec2_instance: str, ec2_instance_states: InstanceStates
+) -> None:
+ """
+ ----inputs----
+ schedule:
+ begintime = 10:00
+ endtime = 20:00
+ current time: 5:00
+ instance: running
+ last_desired_state: none (not seen before)
+
+ ----expect----
+ instance: stopped
+ """
+ # ----------------------------Event Definition--------------------------#
+ context = build_context(
+ current_dt=quick_time(5, 0, 0),
+ schedules={
+ "test-schedule": InstanceSchedule(
+ name="test-schedule",
+ stop_new_instances=True,
+ periods=[
+ {
+ "period": RunningPeriod(
+ name="test-period",
+ begintime=datetime.time(10, 0, 0),
+ endtime=datetime.time(20, 0, 0),
+ )
+ }
+ ],
+ )
+ },
+ )
+
+ event = build_scheduling_event(context)
+ # ----------------------------EC2 Instance-------------------------#
+ ec2_client: EC2Client = boto3.client("ec2")
+ ec2_client.start_instances(InstanceIds=[ec2_instance])
+
+ # ------------------------Last Desired State------------------------#
+ # none set (never been seen before)
+
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ # ---------------------validate result---------------------#
+ assert get_current_state(ec2_instance) == "stopped"
+
+
+def test_instance_does_not_stop_when_it_is_not_new(
+ ec2_instance: str, ec2_instance_states: InstanceStates
+) -> None:
+ """
+ the stop new instances flag should only affect instances that are "new" to the scheduler
+ ----inputs----
+ schedule:
+ begintime = 10:00
+ endtime = 20:00
+ current time: 5:00
+ instance: running
+ last_desired_state: stopped (normal expected from being outside a period)
+
+ ----expect----
+ instance: running
+ """
+ # ----------------------------Event Definition--------------------------#
+ context = build_context(
+ current_dt=quick_time(5, 0, 0),
+ schedules={
+ "test-schedule": InstanceSchedule(
+ name="test-schedule",
+ stop_new_instances=True,
+ periods=[
+ {
+ "period": RunningPeriod(
+ name="test-period",
+ begintime=datetime.time(10, 0, 0),
+ endtime=datetime.time(20, 0, 0),
+ )
+ }
+ ],
+ )
+ },
+ )
+
+ event = build_scheduling_event(context)
+ # ----------------------------EC2 Instance-------------------------#
+ ec2_client: EC2Client = boto3.client("ec2")
+ ec2_client.start_instances(InstanceIds=[ec2_instance])
+
+ # ------------------------Last Desired State------------------------#
+ ec2_instance_states.set_instance_state(ec2_instance, "stopped")
+ ec2_instance_states.save()
+
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ # ---------------------validate result---------------------#
+ assert get_current_state(ec2_instance) == "running"
+
+
+def test_new_instance_does_not_stop_when_outside_period_and_flag_is_not_set(
+ ec2_instance: str, ec2_instance_states: InstanceStates
+) -> None:
+ """
+ ----inputs----
+ schedule:
+ begintime = 10:00
+ endtime = 20:00
+ current time: 5:00
+ instance: running
+ last_desired_state: none (not seen before)
+
+ ----expect----
+ instance: stopped
+ """
+ # ----------------------------Event Definition--------------------------#
+ context = build_context(
+ current_dt=quick_time(5, 0, 0),
+ schedules={
+ "test-schedule": InstanceSchedule(
+ name="test-schedule",
+ stop_new_instances=False,
+ periods=[
+ {
+ "period": RunningPeriod(
+ name="test-period",
+ begintime=datetime.time(10, 0, 0),
+ endtime=datetime.time(20, 0, 0),
+ )
+ }
+ ],
+ )
+ },
+ )
+
+ event = build_scheduling_event(context)
+ # ----------------------------EC2 Instance-------------------------#
+ ec2_client: EC2Client = boto3.client("ec2")
+ ec2_client.start_instances(InstanceIds=[ec2_instance])
+
+ # ------------------------Last Desired State------------------------#
+ # none set (never been seen before)
+
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ # ---------------------validate result---------------------#
+ assert get_current_state(ec2_instance) == "running"
+
+
+def test_new_instance_does_not_stop_when_inside_period_and_flag_is_set(
+ ec2_instance: str, ec2_instance_states: InstanceStates
+) -> None:
+ """
+ flag should only stop instances that are newly detected when outside a valid running period
+ ----inputs----
+ schedule:
+ begintime = 10:00
+ endtime = 20:00
+ current time: 15:00
+ instance: running
+ last_desired_state: none (not seen before)
+
+ ----expect----
+ instance: running
+ """
+ # ----------------------------Event Definition--------------------------#
+ context = build_context(
+ current_dt=quick_time(15, 0, 0),
+ schedules={
+ "test-schedule": InstanceSchedule(
+ name="test-schedule",
+ stop_new_instances=True,
+ periods=[
+ {
+ "period": RunningPeriod(
+ name="test-period",
+ begintime=datetime.time(10, 0, 0),
+ endtime=datetime.time(20, 0, 0),
+ )
+ }
+ ],
+ )
+ },
+ )
+
+ event = build_scheduling_event(context)
+ # ----------------------------EC2 Instance-------------------------#
+ ec2_client: EC2Client = boto3.client("ec2")
+ ec2_client.start_instances(InstanceIds=[ec2_instance])
+
+ # ------------------------Last Desired State------------------------#
+ # none set (never been seen before)
+
+ # -------------------run handler------------------------#
+ handler = SchedulingRequestHandler(event, MockLambdaContext())
+ handler.handle_request()
+
+ # ---------------------validate result---------------------#
+ assert get_current_state(ec2_instance) == "running"
diff --git a/source/app/tests/logger.py b/source/app/tests/logger.py
new file mode 100644
index 00000000..8ea01f36
--- /dev/null
+++ b/source/app/tests/logger.py
@@ -0,0 +1,25 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from typing import Any
+
+from instance_scheduler.util.logger import Logger
+
+
+class MockLogger(Logger):
+ def __init__(self) -> None:
+ Logger.__init__(self, log_group="", log_stream="", topic_arn="")
+
+ def info(self, _: str, *__: Any) -> None:
+ """noop"""
+
+ def error(self, _: str, *__: Any) -> None:
+ """noop"""
+
+ def warning(self, _: str, *__: Any) -> None:
+ """noop"""
+
+ def debug(self, _: str, *__: Any) -> None:
+ """noop"""
+
+ def flush(self) -> None:
+ """noop"""
diff --git a/source/app/tests/maint_win/__init__.py b/source/app/tests/maint_win/__init__.py
new file mode 100644
index 00000000..04f8b7b7
--- /dev/null
+++ b/source/app/tests/maint_win/__init__.py
@@ -0,0 +1,2 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
diff --git a/source/app/tests/maint_win/test_ec2_ssm.py b/source/app/tests/maint_win/test_ec2_ssm.py
new file mode 100644
index 00000000..da51e644
--- /dev/null
+++ b/source/app/tests/maint_win/test_ec2_ssm.py
@@ -0,0 +1,245 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from datetime import time
+from typing import Any, Final
+from unittest.mock import MagicMock, patch
+
+from boto3.session import Session
+from freezegun import freeze_time
+from pytest_mock import MockFixture
+
+from instance_scheduler.maint_win import EC2SSMMaintenanceWindows
+from tests.logger import MockLogger
+
+next_execution_time: Final = "2020-04-09T19:00Z"
+
+
+def test_ssm_maintenance_windows_1(mocker: MockFixture) -> None:
+ window_list = [
+ {
+ "WindowId": "mw-018e7137c74304cb5",
+ "Name": "mon-1",
+ "Enabled": True,
+ "Duration": 1,
+ "Cutoff": 0,
+ "Schedule": "cron(0 0 19 ? * * *)",
+ "NextExecutionTime": next_execution_time,
+ }
+ ]
+ maint_win: Any = EC2SSMMaintenanceWindows(
+ hub_session=Session(),
+ spoke_session=Session(),
+ spoke_account_id="111111111111",
+ table_name="maint-win-table",
+ scheduler_interval=10,
+ logger=MockLogger(),
+ )
+ mocker.patch.object(maint_win, "get_ssm_windows")
+ maint_win.get_ssm_windows.return_value = window_list
+ session = ""
+ account = "1111"
+ region = "us-east-1"
+
+ response = maint_win.ssm_maintenance_windows(session, account, region)
+
+ assert response["mon-1"].periods[0]["period"].name == "mon-1-period"
+ assert response["mon-1"].periods[0]["period"].begintime == time(18, 40)
+ assert response["mon-1"].periods[0]["period"].endtime == time(20, 0)
+ assert response["mon-1"].periods[0]["period"].months == {4}
+ assert response["mon-1"].periods[0]["period"].monthdays == {9}
+
+
+def test_ssm_maintenance_windows_2(mocker: MockFixture) -> None:
+ window_list = [
+ {
+ "WindowId": "mw-018e7137c74304cb5",
+ "Name": "mon-1",
+ "Enabled": True,
+ "Duration": 1,
+ "Cutoff": 0,
+ "Schedule": "cron(0 0 19 ? * * *)",
+ "NextExecutionTime": "2020-05-10T15:00Z",
+ }
+ ]
+ maint_win: Any = EC2SSMMaintenanceWindows(
+ hub_session=Session(),
+ spoke_session=Session(),
+ spoke_account_id="111111111111",
+ table_name="maint-win-table",
+ scheduler_interval=10,
+ logger=MockLogger(),
+ )
+ mocker.patch.object(maint_win, "get_ssm_windows")
+ maint_win.get_ssm_windows.return_value = window_list
+ session = ""
+ account = "1111"
+ region = "us-east-1"
+ response = maint_win.ssm_maintenance_windows(session, account, region)
+
+ assert response["mon-1"].periods[0]["period"].name == "mon-1-period"
+ assert response["mon-1"].periods[0]["period"].begintime == time(14, 40)
+ assert response["mon-1"].periods[0]["period"].endtime == time(16, 0)
+ assert response["mon-1"].periods[0]["period"].months == {5}
+ assert response["mon-1"].periods[0]["period"].monthdays == {10}
+
+
+@freeze_time("2020-05-10 15:30:34")
+def test_check_window_running_1() -> None:
+ window = {
+ "WindowId": "mw-018e7137c74304cb5",
+ "Name": "mon-1",
+ "Enabled": True,
+ "Duration": 1,
+ "Cutoff": 0,
+ "Schedule": "cron(0 10 19 ? * * *)",
+ "NextExecutionTime": "2020-05-10T15:00Z",
+ }
+ mw = EC2SSMMaintenanceWindows(
+ hub_session=Session(),
+ spoke_session=Session(),
+ spoke_account_id="",
+ table_name="",
+ scheduler_interval=5,
+ logger=MockLogger(),
+ )
+ assert mw.check_window_running(window)
+
+
+@freeze_time("2020-05-11 15:30:34")
+def test_check_window_running_2() -> None:
+ window = {
+ "WindowId": "mw-018e7137c74304cb5",
+ "Name": "mon-1",
+ "Enabled": True,
+ "Duration": 1,
+ "Cutoff": 0,
+ "Schedule": "cron(0 10 19 ? * * *)",
+ "NextExecutionTime": "2020-05-10T15:00Z",
+ }
+ mw = EC2SSMMaintenanceWindows(
+ hub_session=Session(),
+ spoke_session=Session(),
+ spoke_account_id="",
+ table_name="",
+ scheduler_interval=5,
+ logger=MockLogger(),
+ )
+ assert not mw.check_window_running(window)
+
+
+@patch("instance_scheduler.maint_win.ec2_ssm.EC2SSMMaintenanceWindowStore")
+def test_get_ssm_windows(mock_store: MagicMock) -> None:
+ window_list = [
+ {
+ "WindowId": "mw-018e7137c74304cb5",
+ "Name": "mon-1",
+ "Duration": 1,
+ "NextExecutionTime": next_execution_time,
+ }
+ ]
+ maint_win: Any = EC2SSMMaintenanceWindows(
+ hub_session=Session(),
+ spoke_session=Session(),
+ spoke_account_id="111111111111",
+ table_name="maint-win-table",
+ scheduler_interval=10,
+ logger=MockLogger(),
+ )
+ mock_store.return_value.get_ssm_windows_db.return_value = window_list
+
+ session = ""
+ account = "1111"
+ region = "us-east-1"
+ with patch.object(maint_win, "get_ssm_windows_service"), patch.object(
+ maint_win, "process_ssm_window"
+ ):
+ response = maint_win.get_ssm_windows(session, account, region)
+
+ assert response == window_list
+
+
+@patch("instance_scheduler.maint_win.ec2_ssm.EC2SSMMaintenanceWindowStore")
+def test_process_ssm_window_1(mock_store: MagicMock) -> None:
+ ssm_windows_db = [
+ {
+ "WindowId": "mw-018e7137c74304cb5",
+ "Name": "mon-1",
+ "Duration": 1,
+ "NextExecutionTime": next_execution_time,
+ },
+ {
+ "WindowId": "mw-018e7137c74304wb5",
+ "Name": "mon-2",
+ "Duration": 1,
+ "NextExecutionTime": "2020-04-10T19:00Z",
+ },
+ ]
+ window = {
+ "WindowId": "mw-018e7137c74304cb5",
+ "Name": "mon-1",
+ "Duration": 1,
+ "NextExecutionTime": next_execution_time,
+ }
+ maint_win: Any = EC2SSMMaintenanceWindows(
+ hub_session=Session(),
+ spoke_session=Session(),
+ spoke_account_id="111111111111",
+ table_name="maint-win-table",
+ scheduler_interval=10,
+ logger=MockLogger(),
+ )
+ account = "1111"
+ region = "us-east-1"
+ maint_win.process_ssm_window(
+ window=window, ssm_windows_db=ssm_windows_db, account=account, region=region
+ )
+ mock_store.return_value.put_window_dynamodb.assert_called_with(
+ window=window, account=account, region=region
+ )
+
+
+@patch("instance_scheduler.maint_win.ec2_ssm.EC2SSMMaintenanceWindowStore")
+def test_process_ssm_window_2(mock_store: MagicMock) -> None:
+ ssm_windows_db = [
+ {
+ "WindowId": "mw-018e7137c74304cb5",
+ "Name": "mon-1",
+ "Enabled": True,
+ "Duration": 1,
+ "Cutoff": 0,
+ "Schedule": "cron(0 10 19 ? * * *)",
+ "NextExecutionTime": next_execution_time,
+ },
+ {
+ "WindowId": "mw-018e7137c74304wb5",
+ "Name": "mon-2",
+ "Enabled": False,
+ "Duration": 1,
+ "Cutoff": 0,
+ "Schedule": "cron(0 10 19 ? * * *)",
+ "NextExecutionTime": "2020-04-10T19:00Z",
+ },
+ ]
+ window = {
+ "WindowId": "mw-018e7137c74304cb5",
+ "Name": "mon-3",
+ "Enabled": True,
+ "Duration": 1,
+ "Cutoff": 0,
+ "Schedule": "cron(0 10 19 ? * * *)",
+ "NextExecutionTime": next_execution_time,
+ }
+ maint_win: Any = EC2SSMMaintenanceWindows(
+ hub_session=Session(),
+ spoke_session=Session(),
+ spoke_account_id="111111111111",
+ table_name="maint-win-table",
+ scheduler_interval=10,
+ logger=MockLogger(),
+ )
+ account = "1111"
+ region = "us-east-1"
+ maint_win.process_ssm_window(window, ssm_windows_db, account, region)
+ mock_store.return_value.put_window_dynamodb.assert_called_with(
+ window=window, account=account, region=region
+ )
diff --git a/source/app/tests/model/__init__.py b/source/app/tests/model/__init__.py
new file mode 100644
index 00000000..04f8b7b7
--- /dev/null
+++ b/source/app/tests/model/__init__.py
@@ -0,0 +1,2 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
diff --git a/source/app/tests/model/test_maint_win.py b/source/app/tests/model/test_maint_win.py
new file mode 100644
index 00000000..c45eee71
--- /dev/null
+++ b/source/app/tests/model/test_maint_win.py
@@ -0,0 +1,232 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from dataclasses import replace
+from datetime import datetime, timezone
+from typing import TYPE_CHECKING, Final
+from zoneinfo import ZoneInfo
+
+from dateutil.parser import isoparse
+from pytest import raises
+
+from instance_scheduler.model import (
+ EC2SSMMaintenanceWindow,
+ EC2SSMMaintenanceWindowValidationError,
+)
+
+if TYPE_CHECKING:
+ from mypy_boto3_dynamodb.type_defs import GetItemOutputTypeDef
+ from mypy_boto3_ssm.type_defs import MaintenanceWindowIdentityTypeDef
+else:
+ GetItemOutputTypeDef = object
+ MaintenanceWindowIdentityTypeDef = object
+
+
+def example_maint_win() -> EC2SSMMaintenanceWindow:
+ return EC2SSMMaintenanceWindow(
+ account_id="111111111111",
+ region="us-east-1",
+ window_id="mw-00000000000000000",
+ window_name="my-window",
+ schedule_timezone=ZoneInfo("UTC"),
+ next_execution_time=datetime(year=2023, month=6, day=23, tzinfo=timezone.utc),
+ duration=1,
+ )
+
+
+def test_validate_account_id() -> None:
+ invalid_account_ids: Final = (
+ "",
+ "invalid",
+ "00000000000",
+ "0000000000000",
+ " 000000000000",
+ )
+ for invalid_account_id in invalid_account_ids:
+ with raises(EC2SSMMaintenanceWindowValidationError):
+ replace(example_maint_win(), account_id=invalid_account_id)
+
+
+def test_validate_region() -> None:
+ with raises(EC2SSMMaintenanceWindowValidationError):
+ replace(example_maint_win(), region="")
+
+
+def test_validate_window_id() -> None:
+ invalid_window_ids: Final = (
+ "",
+ "invalid",
+ "mw-0000000000000000",
+ "mw-000000000000000000",
+ "mw-00000000000000000 ",
+ )
+ for invalid_window_id in invalid_window_ids:
+ with raises(EC2SSMMaintenanceWindowValidationError):
+ replace(example_maint_win(), window_id=invalid_window_id)
+
+
+def test_validate_window_name() -> None:
+ invalid_window_names: Final = (
+ "",
+ "mw",
+ "invalid-@",
+ " otherwise-valid",
+ "a" * 129,
+ )
+ for invalid_window_name in invalid_window_names:
+ with raises(EC2SSMMaintenanceWindowValidationError):
+ replace(example_maint_win(), window_name=invalid_window_name)
+
+
+def test_validate_next_execution_time() -> None:
+ with raises(EC2SSMMaintenanceWindowValidationError):
+ # utcnow returns a naive datetime
+ replace(example_maint_win(), next_execution_time=datetime.utcnow())
+
+
+def test_validate_duration() -> None:
+ invalid_durations: Final = (0, -10, 30)
+ for invalid_duration in invalid_durations:
+ with raises(EC2SSMMaintenanceWindowValidationError):
+ replace(example_maint_win(), duration=invalid_duration)
+
+
+def test_to_item() -> None:
+ account_id = "111111111111"
+ region = "us-east-1"
+ window_id = "mw-00000000000000000"
+ window_name = "my-window"
+ schedule_timezone = "Europe/Amsterdam"
+ next_execution_time = datetime(
+ year=2023, month=6, day=23, tzinfo=ZoneInfo(schedule_timezone)
+ )
+ duration = 1
+ maint_win = EC2SSMMaintenanceWindow(
+ account_id=account_id,
+ region=region,
+ window_id=window_id,
+ window_name=window_name,
+ schedule_timezone=ZoneInfo(schedule_timezone),
+ next_execution_time=next_execution_time,
+ duration=duration,
+ )
+ assert maint_win.to_item() == {
+ "account-region": {"S": f"{account_id}:{region}"},
+ "WindowId": {"S": window_id},
+ "Name": {"S": window_name},
+ "ScheduleTimezone": {"S": schedule_timezone},
+ "NextExecutionTime": {"S": next_execution_time.isoformat()},
+ "Duration": {"N": str(duration)},
+ }
+
+
+def test_to_key() -> None:
+ account_id = "111111111111"
+ region = "us-east-1"
+ window_name = "my-window"
+ window = replace(
+ example_maint_win(),
+ account_id=account_id,
+ region=region,
+ window_name=window_name,
+ )
+ assert window.to_key() == {
+ "account-region": f"{account_id}:{region}",
+ "Name": window_name,
+ }
+
+
+def test_from_identity() -> None:
+ account_id = "111111111111"
+ region = "us-east-1"
+ window_id = "mw-00000000000000000"
+ window_name = "my-window"
+ schedule_timezone = "Asia/Tokyo"
+ next_execution_time = datetime(
+ year=2023, month=6, day=23, tzinfo=ZoneInfo(schedule_timezone)
+ )
+ duration = 1
+ identity: MaintenanceWindowIdentityTypeDef = {
+ "WindowId": window_id,
+ "Name": window_name,
+ "ScheduleTimezone": schedule_timezone,
+ "NextExecutionTime": next_execution_time.isoformat(),
+ "Duration": duration,
+ }
+ maint_win = EC2SSMMaintenanceWindow.from_identity(
+ identity=identity, account_id=account_id, region=region
+ )
+ assert maint_win.account_id == account_id
+ assert maint_win.region == region
+ assert maint_win.window_id == window_id
+ assert maint_win.window_name == window_name
+ assert maint_win.schedule_timezone == ZoneInfo(schedule_timezone)
+ assert maint_win.next_execution_time == next_execution_time
+ assert maint_win.duration == duration
+
+
+def test_from_identity_no_timezone() -> None:
+ next_execution_time = datetime(year=2023, month=6, day=23, tzinfo=timezone.utc)
+ identity: MaintenanceWindowIdentityTypeDef = {
+ "WindowId": "mw-00000000000000000",
+ "Name": "my-window",
+ "NextExecutionTime": next_execution_time.isoformat(),
+ "Duration": 1,
+ }
+ maint_win = EC2SSMMaintenanceWindow.from_identity(
+ identity=identity, account_id="111111111111", region="us-east-1"
+ )
+ assert maint_win.schedule_timezone == ZoneInfo("UTC")
+ assert maint_win.next_execution_time == next_execution_time
+
+
+def test_from_identity_utc_offset_shorthand() -> None:
+ next_execution_time = "2023-06-24T00:00Z"
+ identity: MaintenanceWindowIdentityTypeDef = {
+ "WindowId": "mw-00000000000000000",
+ "Name": "my-window",
+ "NextExecutionTime": next_execution_time,
+ "Duration": 1,
+ }
+ maint_win = EC2SSMMaintenanceWindow.from_identity(
+ identity=identity, account_id="111111111111", region="us-east-1"
+ )
+ assert maint_win.schedule_timezone == ZoneInfo("UTC")
+ assert maint_win.next_execution_time == isoparse(next_execution_time)
+
+
+def test_from_item() -> None:
+ account_id = "111111111111"
+ region = "us-east-1"
+ window_id = "mw-00000000000000000"
+ window_name = "my-window"
+ schedule_timezone = "Asia/Tokyo"
+ next_execution_time = datetime(
+ year=2023, month=6, day=23, tzinfo=ZoneInfo(schedule_timezone)
+ )
+ duration = 1
+ item: GetItemOutputTypeDef = {
+ "Item": {
+ "account-region": {"S": f"{account_id}:{region}"},
+ "Name": {"S": window_name},
+ "WindowId": {"S": window_id},
+ "ScheduleTimezone": {"S": schedule_timezone},
+ "NextExecutionTime": {"S": next_execution_time.isoformat()},
+ "Duration": {"N": str(duration)},
+ },
+ "ConsumedCapacity": {},
+ "ResponseMetadata": {
+ "RequestId": "",
+ "HostId": "",
+ "HTTPStatusCode": 200,
+ "HTTPHeaders": {},
+ "RetryAttempts": 0,
+ },
+ }
+ maint_win = EC2SSMMaintenanceWindow.from_item(item)
+ assert maint_win.account_id == account_id
+ assert maint_win.region == region
+ assert maint_win.window_id == window_id
+ assert maint_win.window_name == window_name
+ assert maint_win.schedule_timezone == ZoneInfo(schedule_timezone)
+ assert maint_win.next_execution_time == next_execution_time
+ assert maint_win.duration == duration
diff --git a/source/app/tests/model/test_maint_win_store.py b/source/app/tests/model/test_maint_win_store.py
new file mode 100644
index 00000000..d40bc2f0
--- /dev/null
+++ b/source/app/tests/model/test_maint_win_store.py
@@ -0,0 +1,84 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from datetime import datetime, timezone
+from typing import TYPE_CHECKING, Final
+from unittest.mock import ANY
+
+from boto3 import Session, client
+from pytest import fixture
+
+from instance_scheduler.model import EC2SSMMaintenanceWindowStore
+from instance_scheduler.util.app_env import AppEnv
+from tests.logger import MockLogger
+
+if TYPE_CHECKING:
+ from mypy_boto3_dynamodb.client import DynamoDBClient
+ from mypy_boto3_ssm.type_defs import MaintenanceWindowIdentityTypeDef
+else:
+ DynamoDBClient = object
+ MaintenanceWindowIdentityTypeDef = object
+
+
+@fixture
+def maint_win_table(moto_dynamodb: None, app_env: AppEnv) -> str:
+ maint_win_table_name: Final = app_env.maintenance_window_table_name
+ ddb: Final[DynamoDBClient] = client("dynamodb")
+ ddb.create_table(
+ AttributeDefinitions=[
+ {"AttributeName": "Name", "AttributeType": "S"},
+ {"AttributeName": "account-region", "AttributeType": "S"},
+ ],
+ TableName=maint_win_table_name,
+ KeySchema=[
+ {"AttributeName": "Name", "KeyType": "HASH"},
+ {"AttributeName": "account-region", "KeyType": "RANGE"},
+ ],
+ BillingMode="PAY_PER_REQUEST",
+ )
+ return maint_win_table_name
+
+
+def test_maint_win_store(maint_win_table: str) -> None:
+ account_id = "111111111111"
+ region = "us-east-1"
+ window_name = "my-window"
+ next_execution_time = datetime(year=2023, month=6, day=23, tzinfo=timezone.utc)
+ duration = 1
+ window_id = "mw-00000000000000000"
+ schedule_timezone = "UTC"
+ format_string = "%Y-%m-%dT%H:%M%z"
+ window: MaintenanceWindowIdentityTypeDef = {
+ "Name": window_name,
+ "NextExecutionTime": next_execution_time.strftime(format_string),
+ "Duration": duration,
+ "WindowId": window_id,
+ "ScheduleTimezone": schedule_timezone,
+ }
+
+ store = EC2SSMMaintenanceWindowStore(
+ session=Session(), table_name=maint_win_table, logger=MockLogger()
+ )
+
+ windows = store.get_ssm_windows_db(account=account_id, region=region)
+ assert windows == []
+
+ store.put_window_dynamodb(window=window, account=account_id, region=region)
+ windows = store.get_ssm_windows_db(account=account_id, region=region)
+
+ assert len(windows) == 1
+ account_region = f"{account_id}:{region}"
+ assert windows[0] == {
+ "account-region": account_region,
+ "Name": window_name,
+ "Duration": duration,
+ "WindowId": window_id,
+ "TimeToLive": ANY,
+ "NextExecutionTime": next_execution_time.strftime(format_string),
+ "ScheduleTimezone": schedule_timezone,
+ }
+
+ window["account-region"] = account_region # type: ignore[typeddict-unknown-key]
+ store.delete_window(window)
+
+ windows = store.get_ssm_windows_db(account=account_id, region=region)
+ assert windows == []
diff --git a/source/app/tests/plugins/env_vars.py b/source/app/tests/plugins/env_vars.py
deleted file mode 100644
index 87424605..00000000
--- a/source/app/tests/plugins/env_vars.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-
-import os
-import pytest
-
-TABLE_NAME = "mock-schedule-state-table"
-CONFIG_TABLE_NAME = "mock-schedule-state-table"
-
-
-@pytest.hookimpl(tryfirst=True)
-def pytest_load_initial_conftests():
- os.environ["SCHEDULE_STATES_TABLE"] = TABLE_NAME
- os.environ["CONFIG_TABLE"] = CONFIG_TABLE_NAME
- os.environ["LOG_GROUP"] = "instance-scheduler-logs"
- os.environ["ACCOUNT"] = "111111111111"
- os.environ["SSM_EXECUTION_ROLE_NAME"] = "role/role_name"
- os.environ["SSM_ADMIN_ROLE_NAME"] = "role/role_name"
- os.environ["RDS_INSTANCES_START_SSM_DOC"] = "RDS_INSTANCES_START_SSM_DOC"
- os.environ["RDS_INSTANCES_STOP_SSM_DOC"] = "RDS_INSTANCES_STOP_SSM_DOC"
- os.environ["RDS_CLUSTERS_START_SSM_DOC"] = "RDS_CLUSTERS_START_SSM_DOC"
- os.environ["RDS_CLUSTERS_STOP_SSM_DOC"] = "RDS_CLUSTERS_STOP_SSM_DOC"
- os.environ["EC2_START_SSM_DOC"] = "EC2_START_SSM_DOC"
- os.environ["EC2_STOP_SSM_DOC"] = "EC2_STOP_SSM_DOC"
- os.environ["TRACE"] = "DEBUG"
- os.environ["aws_partition"] = "aws"
- os.environ["namespace"] = "test"
- os.environ["AWS_REGION"] = "us-east-1"
- os.environ["AWS_DEFAULT_REGION"] = "us-east-1"
- os.environ["SOLUTION_ID"] = "SOTestID"
- os.environ["AWS_ACCOUNT"] = "123456789012"
diff --git a/source/app/tests/pytest.ini b/source/app/tests/pytest.ini
deleted file mode 100644
index d8281227..00000000
--- a/source/app/tests/pytest.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[pytest]
-addopts = -sv -p tests.plugins.env_vars
-log_cli = true
-log_level=INFO
diff --git a/source/app/tests/requesthandlers/test_eventbus_request_handler.py b/source/app/tests/requesthandlers/test_eventbus_request_handler.py
deleted file mode 100644
index b18f0713..00000000
--- a/source/app/tests/requesthandlers/test_eventbus_request_handler.py
+++ /dev/null
@@ -1,82 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-from contextlib import contextmanager
-from os import environ
-from instance_scheduler.requesthandlers.eventbus_request_handler import (
- EventBusRequestHandler,
-)
-from instance_scheduler.util.dynamodb_utils import DynamoDBUtils
-
-table_name = environ["CONFIG_TABLE"]
-
-
-@contextmanager
-def ddb_setup(dynamodb_client_resource):
- dynamodb_client_resource.create_table(
- TableName=table_name,
- KeySchema=[
- {"AttributeName": "name", "KeyType": "HASH"},
- {"AttributeName": "type", "KeyType": "HASH"},
- ],
- AttributeDefinitions=[
- {"AttributeName": "name", "AttributeType": "S"},
- {"AttributeName": "type", "AttributeType": "S"},
- ],
- ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5},
- )
- yield
-
-
-def test_handler(dynamodb_client_resource):
- with ddb_setup(dynamodb_client_resource):
- createEvent = {
- "version": "0",
- "id": "c4556ddf-88ad-1b22-e482-19f2d72eb7e3",
- "detail-type": "Parameter Store Change",
- "source": "aws.ssm",
- "account": "111111111111",
- "time": "2021-08-19T06:26:38Z",
- "region": "us-east-1",
- "resources": [
- "arn:aws:ssm:us-east-1:111111111111:parameter/scheduler/do-not-delete-manually/static"
- ],
- "detail": {
- "name": "/scheduler/do-not-delete-manually/static",
- "type": "String",
- "operation": "Create",
- },
- }
- dynamodb_table = DynamoDBUtils.get_dynamodb_table_resource_ref(table_name)
- dynamodb_table.put_item(
- Item={"type": "config", "name": "scheduler", "namespace": "static"}
- )
- handler = EventBusRequestHandler(createEvent, {})
- response = handler.is_handling_request(createEvent)
- assert response == True
-
- response = handler.handle_request()
- assert response == "Exiting event bus request handler"
- deleteEvent = {
- "version": "0",
- "id": "c4556ddf-88ad-1b22-e482-19f2d72eb7e3",
- "detail-type": "Parameter Store Change",
- "source": "aws.ssm",
- "account": "111111111111",
- "time": "2021-08-19T06:26:38Z",
- "region": "us-east-1",
- "resources": [
- "arn:aws:ssm:us-east-1:111111111111:parameter/scheduler/do-not-delete-manually/static"
- ],
- "detail": {
- "name": "/scheduler/do-not-delete-manually/static",
- "type": "String",
- "operation": "Delete",
- },
- }
- handler = EventBusRequestHandler(deleteEvent, {})
- response = handler.is_handling_request(deleteEvent)
- assert response == True
-
- response = handler.handle_request()
- assert response == "Exiting event bus request handler"
diff --git a/source/app/tests/requesthandlers/test_scheduler_setup_handler.py b/source/app/tests/requesthandlers/test_scheduler_setup_handler.py
deleted file mode 100644
index b2db72e6..00000000
--- a/source/app/tests/requesthandlers/test_scheduler_setup_handler.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-from instance_scheduler.requesthandlers.scheduler_setup_handler import (
- SchedulerSetupHandler,
-)
-from unittest import mock
-from unittest.mock import MagicMock
-
-
-def test_a_valid_org_id_pattern():
- handler = SchedulerSetupHandler(
- {"ResourceProperties": {"stack_version": "test"}}, {}
- )
- response = handler.get_valid_org_id("o-x1mhq1lvsr")
- assert response != "o-x1mhq1lvsr"
-
-
-def test_an_invalid_org_id_pattern():
- handler = SchedulerSetupHandler(
- {"ResourceProperties": {"stack_version": "test"}}, {}
- )
- response = handler.get_valid_org_id("111111111111,222222222222")
- assert response == None
diff --git a/source/app/tests/schedulers/__init__.py b/source/app/tests/schedulers/__init__.py
new file mode 100644
index 00000000..04f8b7b7
--- /dev/null
+++ b/source/app/tests/schedulers/__init__.py
@@ -0,0 +1,2 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
diff --git a/source/app/tests/schedulers/test_ec2_service.py b/source/app/tests/schedulers/test_ec2_service.py
deleted file mode 100644
index 405ed871..00000000
--- a/source/app/tests/schedulers/test_ec2_service.py
+++ /dev/null
@@ -1,191 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-from unittest import mock
-import os
-from instance_scheduler import configuration
-
-mock.patch.dict(os.environ, {configuration.ENV_SCHEDULE_FREQUENCY: "10"}).start()
-mock.patch.dict(os.environ, {"MAINTENANCE_WINDOW_TABLE": "test_table"}).start()
-
-from instance_scheduler.schedulers import Ec2Service
-import datetime
-from freezegun import freeze_time
-
-
-def test_ssm_maintenance_windows_1(mocker):
- window_list = [
- {
- "WindowId": "mw-018e7137c74304cb5",
- "Name": "mon-1",
- "Enabled": True,
- "Duration": 1,
- "Cutoff": 0,
- "Schedule": "cron(0 10 19 ? * * *)",
- "NextExecutionTime": "2020-04-09T19:00Z",
- }
- ]
- ec2_service = Ec2Service()
- mocker.patch.object(ec2_service, "get_ssm_windows")
- ec2_service.get_ssm_windows.return_value = window_list
- mocker.patch.object(ec2_service, "_logger")
- session = ""
- account = "1111"
- region = "us-east-1"
- context = ""
- response = ec2_service.ssm_maintenance_windows(session, context, account, region)
-
- assert response["mon-1"].periods[0]["period"].name == "mon-1-period"
- assert response["mon-1"].periods[0]["period"].begintime == datetime.time(18, 50)
- assert response["mon-1"].periods[0]["period"].endtime == datetime.time(20, 0)
- assert response["mon-1"].periods[0]["period"].months == {4}
- assert response["mon-1"].periods[0]["period"].monthdays == {9}
-
-
-def test_ssm_maintenance_windows_2(mocker):
- window_list = [
- {
- "WindowId": "mw-018e7137c74304cb5",
- "Name": "mon-1",
- "Enabled": True,
- "Duration": 1,
- "Cutoff": 0,
- "Schedule": "cron(0 10 19 ? * * *)",
- "NextExecutionTime": "2020-05-10T15:00Z",
- }
- ]
- ec2_service = Ec2Service()
- mocker.patch.object(ec2_service, "get_ssm_windows")
- ec2_service.get_ssm_windows.return_value = window_list
- mocker.patch.object(ec2_service, "_logger")
- session = ""
- account = "1111"
- region = "us-east-1"
- context = ""
- response = ec2_service.ssm_maintenance_windows(session, context, account, region)
-
- assert response["mon-1"].periods[0]["period"].name == "mon-1-period"
- assert response["mon-1"].periods[0]["period"].begintime == datetime.time(14, 50)
- assert response["mon-1"].periods[0]["period"].endtime == datetime.time(16, 0)
- assert response["mon-1"].periods[0]["period"].months == {5}
- assert response["mon-1"].periods[0]["period"].monthdays == {10}
-
-
-@freeze_time("2020-05-10 15:30:34")
-def test_check_window_running_1(mocker):
- window = {
- "WindowId": "mw-018e7137c74304cb5",
- "Name": "mon-1",
- "Enabled": True,
- "Duration": 1,
- "Cutoff": 0,
- "Schedule": "cron(0 10 19 ? * * *)",
- "NextExecutionTime": "2020-05-10T15:00Z",
- }
- ec2_service = Ec2Service()
- assert ec2_service.check_window_running(window)
-
-
-@freeze_time("2020-05-11 15:30:34")
-def test_check_window_running_2(mocker):
- window = {
- "WindowId": "mw-018e7137c74304cb5",
- "Name": "mon-1",
- "Enabled": True,
- "Duration": 1,
- "Cutoff": 0,
- "Schedule": "cron(0 10 19 ? * * *)",
- "NextExecutionTime": "2020-05-10T15:00Z",
- }
- ec2_service = Ec2Service()
- assert not ec2_service.check_window_running(window)
-
-
-def test_get_ssm_windows(mocker):
- window_list = [
- {
- "WindowId": "mw-018e7137c74304cb5",
- "Name": "mon-1",
- "Duration": 1,
- "NextExecutionTime": "2020-04-09T19:00Z",
- }
- ]
- ec2_service = Ec2Service()
- mocker.patch.object(ec2_service, "get_ssm_windows_service")
- mocker.patch.object(ec2_service, "get_ssm_windows_db")
- mocker.patch.object(ec2_service, "process_ssm_window")
- mocker.patch.object(ec2_service, "remove_unused_windows")
- ec2_service.get_ssm_windows_db.return_value = window_list
- session = ""
- context = ""
- account = "1111"
- region = "us-east-1"
- response = ec2_service.get_ssm_windows(session, context, account, region)
- assert response == window_list
-
-
-def test_process_ssm_window_1(mocker):
- ssm_windows_db = [
- {
- "WindowId": "mw-018e7137c74304cb5",
- "Name": "mon-1",
- "Duration": 1,
- "NextExecutionTime": "2020-04-09T19:00Z",
- },
- {
- "WindowId": "mw-018e7137c74304wb5",
- "Name": "mon-2",
- "Duration": 1,
- "NextExecutionTime": "2020-04-10T19:00Z",
- },
- ]
- window = {
- "WindowId": "mw-018e7137c74304cb5",
- "Name": "mon-1",
- "Duration": 1,
- "NextExecutionTime": "2020-04-09T19:00Z",
- }
- ec2_service = Ec2Service()
- mocker.patch.object(ec2_service, "put_window_dynamodb")
- account = "1111"
- region = "us-east-1"
- ec2_service.process_ssm_window(window, ssm_windows_db, account, region)
- ec2_service.put_window_dynamodb.assert_called_with(window, account, region)
-
-
-def test_process_ssm_window_2(mocker):
- ssm_windows_db = [
- {
- "WindowId": "mw-018e7137c74304cb5",
- "Name": "mon-1",
- "Enabled": True,
- "Duration": 1,
- "Cutoff": 0,
- "Schedule": "cron(0 10 19 ? * * *)",
- "NextExecutionTime": "2020-04-09T19:00Z",
- },
- {
- "WindowId": "mw-018e7137c74304wb5",
- "Name": "mon-2",
- "Enabled": False,
- "Duration": 1,
- "Cutoff": 0,
- "Schedule": "cron(0 10 19 ? * * *)",
- "NextExecutionTime": "2020-04-10T19:00Z",
- },
- ]
- window = {
- "WindowId": "mw-018e7137c74304cb5",
- "Name": "mon-3",
- "Enabled": True,
- "Duration": 1,
- "Cutoff": 0,
- "Schedule": "cron(0 10 19 ? * * *)",
- "NextExecutionTime": "2020-04-09T19:00Z",
- }
- ec2_service = Ec2Service()
- mocker.patch.object(ec2_service, "put_window_dynamodb")
- account = "1111"
- region = "us-east-1"
- ec2_service.process_ssm_window(window, ssm_windows_db, account, region)
- ec2_service.put_window_dynamodb.assert_called_with(window, account, region)
diff --git a/source/app/tests/schedulers/test_instance_scheduler.py b/source/app/tests/schedulers/test_instance_scheduler.py
index 397dcaff..6aed794d 100644
--- a/source/app/tests/schedulers/test_instance_scheduler.py
+++ b/source/app/tests/schedulers/test_instance_scheduler.py
@@ -1,91 +1,153 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
+from zoneinfo import ZoneInfo
-from unittest import mock
-import os
-from instance_scheduler.configuration.instance_schedule import InstanceSchedule
-from instance_scheduler.schedulers import Ec2Service
-from instance_scheduler.util.named_tuple_builder import as_namedtuple
-from instance_scheduler.schedulers.instance_scheduler import InstanceScheduler
-from unittest.mock import patch, MagicMock, ANY
-
-
-@patch("boto3.Session")
-@patch("instance_scheduler.schedulers.Ec2Service")
-def test_scheduler_uses_regional_sts_endpoint(mock_ec2_service, mock_session):
- mock_session.return_value.client = MagicMock()
- mock_session.return_value.region_name = "executing-region"
- mock_client = mock_session().client
+from boto3 import Session
+from pytest_mock import MockFixture
- scheduler = InstanceScheduler(service=mock_ec2_service, scheduler_configuration={})
+from instance_scheduler.configuration.instance_schedule import (
+ Instance,
+ InstanceSchedule,
+)
+from instance_scheduler.configuration.scheduling_context import SchedulingContext
+from instance_scheduler.schedulers.instance_scheduler import InstanceScheduler
+from instance_scheduler.schedulers.instance_states import InstanceStates
+from instance_scheduler.service import Ec2Service, ServiceArgs
+from tests.integration.helpers.schedule_helpers import quick_time
+from tests.logger import MockLogger
- returned_sts_client = scheduler._sts
- mock_client.assert_called_with(
- "sts",
- region_name="executing-region",
- endpoint_url="https://sts.executing-region.amazonaws.com",
- config=ANY,
+def context() -> SchedulingContext:
+ return SchedulingContext(
+ current_dt=quick_time(10, 0, 0),
+ service="ec2",
+ schedule_clusters=False,
+ tag_name="tag",
+ region="us-east-1",
+ default_timezone=ZoneInfo("UTC"),
+ schedules={},
+ trace=False,
+ enable_ssm_maintenance_windows=False,
+ use_metrics=False,
+ account_id="111111111111",
+ namespace="test",
+ aws_partition="aws",
+ scheduler_role_name="scheduler-role",
+ organization_id="o-0000000000",
+ schedule_lambda_account=True,
+ create_rds_snapshot=False,
)
-def test_get_desired_state_and_type_1(mocker):
- instance = {}
+def test_get_desired_state_and_type_1(moto_sts: None, mocker: MockFixture) -> None:
schedule = InstanceSchedule(
name="test-1",
- periods={},
+ periods=[],
timezone="UTC",
override_status=None,
description=None,
use_metrics=None,
stop_new_instances=None,
- schedule_dt=None,
use_maintenance_window=False,
- ssm_maintenance_window=True,
+ ssm_maintenance_window="",
enforced=False,
hibernate=False,
retain_running=False,
)
- instance["maintenance_window"] = schedule
- instance["account"] = "test"
- instance["region"] = "us-east-1"
- instance["service"] = "ec2"
- instance["id"] = "ut12y21232u"
- inst = as_namedtuple("ec2" + "Instance", instance, excludes=["tags"])
- ec2_service = Ec2Service()
- scheduler_configuration = {}
- scheduler = InstanceScheduler(ec2_service, scheduler_configuration)
+ instance = Instance(
+ maintenance_window=schedule,
+ account="test",
+ region="us-east-1",
+ service="ec2",
+ id="ut12y21232u",
+ allow_resize=True,
+ hibernate=False,
+ state="running",
+ state_name="running",
+ is_running=True,
+ is_terminated=False,
+ current_state="running",
+ instancetype="type",
+ tags={},
+ name="name",
+ schedule_name="schedule",
+ )
+ scheduling_context = context()
+ logger = MockLogger()
+ ec2_service = Ec2Service(
+ ServiceArgs(
+ account_id="",
+ scheduling_context=scheduling_context,
+ logger=logger,
+ session=Session(),
+ stack_name="",
+ )
+ )
+ scheduler = InstanceScheduler(
+ ec2_service,
+ scheduling_context,
+ InstanceStates("", "", logger),
+ "",
+ None,
+ logger,
+ )
mocker.patch.object(scheduler, "_logger")
- inst_state, inst_type = scheduler.get_desired_state_and_type(schedule, inst)
+ inst_state, _ = scheduler.get_desired_state_and_type(schedule, instance)
assert inst_state == "stopped"
-def test_get_desired_state_and_type_2(mocker):
- instance = {}
+def test_get_desired_state_and_type_2(moto_sts: None, mocker: MockFixture) -> None:
schedule = InstanceSchedule(
name="test-1",
- periods={},
+ periods=[],
timezone="UTC",
override_status=None,
description=None,
use_metrics=None,
stop_new_instances=None,
- schedule_dt=None,
use_maintenance_window=True,
- ssm_maintenance_window=True,
+ ssm_maintenance_window="",
enforced=False,
hibernate=False,
retain_running=False,
)
- instance["maintenance_window"] = None
- instance["account"] = "test"
- instance["region"] = "us-east-1"
- instance["service"] = "ec2"
- instance["id"] = "ut12y21232u"
- inst = as_namedtuple("ec2" + "Instance", instance, excludes=["tags"])
- ec2_service = Ec2Service()
- scheduler_configuration = {}
- scheduler = InstanceScheduler(ec2_service, scheduler_configuration)
+ instance = Instance(
+ maintenance_window=None,
+ account="test",
+ region="us-east-1",
+ service="ec2",
+ id="ut12y21232u",
+ allow_resize=True,
+ hibernate=False,
+ state="running",
+ state_name="running",
+ is_running=True,
+ is_terminated=False,
+ current_state="running",
+ instancetype="type",
+ tags={},
+ name="name",
+ schedule_name="schedule",
+ )
+ scheduling_context = context()
+ logger = MockLogger()
+ ec2_service = Ec2Service(
+ ServiceArgs(
+ account_id="",
+ scheduling_context=scheduling_context,
+ logger=logger,
+ session=Session(),
+ stack_name="",
+ )
+ )
+ scheduler = InstanceScheduler(
+ ec2_service,
+ scheduling_context,
+ InstanceStates("", "", logger),
+ "",
+ None,
+ logger,
+ )
mocker.patch.object(scheduler, "_logger")
- inst_state, inst_type = scheduler.get_desired_state_and_type(schedule, inst)
+ inst_state, _ = scheduler.get_desired_state_and_type(schedule, instance)
assert inst_state == "stopped"
diff --git a/source/app/tests/service/__init__.py b/source/app/tests/service/__init__.py
new file mode 100644
index 00000000..04f8b7b7
--- /dev/null
+++ b/source/app/tests/service/__init__.py
@@ -0,0 +1,2 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
diff --git a/source/app/tests/service/test_ec2_service.py b/source/app/tests/service/test_ec2_service.py
new file mode 100644
index 00000000..daf866ae
--- /dev/null
+++ b/source/app/tests/service/test_ec2_service.py
@@ -0,0 +1,427 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from collections.abc import Sequence
+from dataclasses import dataclass, replace
+from itertools import chain
+from typing import TYPE_CHECKING, Final
+from unittest.mock import MagicMock, patch
+
+import boto3
+from boto3.session import Session
+
+from instance_scheduler import ScheduleState
+from instance_scheduler.configuration.instance_schedule import (
+ Instance,
+ InstanceSchedule,
+)
+from instance_scheduler.service import Ec2Service, ServiceArgs
+from instance_scheduler.service.ec2 import EC2StateCode, get_tags
+from tests import ami
+from tests.integration.helpers.schedule_helpers import quick_time
+from tests.integration.helpers.scheduling_context_builder import build_context
+from tests.logger import MockLogger
+
+if TYPE_CHECKING:
+ from mypy_boto3_ec2.client import EC2Client
+ from mypy_boto3_ec2.literals import InstanceStateNameType, InstanceTypeType
+ from mypy_boto3_ec2.type_defs import InstanceTypeDef, TagTypeDef
+else:
+ EC2Client = object
+ InstanceStateNameType = object
+ InstanceTypeType = object
+ InstanceTypeDef = object
+ TagTypeDef = object
+
+
+def test_ec2_state_code() -> None:
+ assert EC2StateCode.PENDING.value == 0
+ assert EC2StateCode.RUNNING.value == 16
+ assert EC2StateCode.SHUTTING_DOWN.value == 32
+ assert EC2StateCode.TERMINATED.value == 48
+ assert EC2StateCode.STOPPING.value == 64
+ assert EC2StateCode.STOPPED.value == 80
+
+
+def test_get_tags() -> None:
+ assert get_tags({}) == {}
+
+ instance: Final[InstanceTypeDef] = {
+ "Tags": [
+ {"Key": "foo", "Value": "bar"},
+ {"Key": "baz", "Value": "qux"},
+ ]
+ }
+
+ assert get_tags(instance) == {"foo": "bar", "baz": "qux"}
+
+
+def mock_service_args() -> ServiceArgs:
+ return ServiceArgs(
+ account_id="111111111111",
+ scheduling_context=build_context(quick_time(0, 0, 0)),
+ logger=MockLogger(),
+ session=Session(),
+ stack_name="",
+ )
+
+
+def test_ec2_service_attributes() -> None:
+ service = Ec2Service(mock_service_args())
+
+ assert service.service_name == "ec2"
+ assert service.allow_resize
+
+
+@dataclass(frozen=True)
+class InstancesOfStatus:
+ qty: int
+ all_ids: Sequence[str]
+ running_ids: Sequence[str]
+ stopped_ids: Sequence[str]
+ terminated_ids: Sequence[str]
+
+
+def create_instances_of_status(
+ ec2: EC2Client,
+ *,
+ instance_type: InstanceTypeType,
+ qty_running: int = 0,
+ qty_stopped: int = 0,
+ qty_terminated: int = 0,
+) -> InstancesOfStatus:
+ total_qty: Final = qty_running + qty_stopped + qty_terminated
+ run_response = ec2.run_instances(
+ ImageId=ami, InstanceType=instance_type, MinCount=total_qty, MaxCount=total_qty
+ )
+ instance_ids = [instance["InstanceId"] for instance in run_response["Instances"]]
+ assert (
+ len(instance_ids) == total_qty
+ ), "Failed to create the right number of instances"
+
+ running_ids = instance_ids[0:qty_running]
+ stopped_ids = instance_ids[qty_running : qty_running + qty_stopped]
+ terminated_ids = instance_ids[qty_running + qty_stopped :]
+
+ ec2.get_waiter("instance_running").wait(InstanceIds=instance_ids)
+
+ ec2.stop_instances(InstanceIds=stopped_ids)
+ if terminated_ids:
+ ec2.terminate_instances(InstanceIds=terminated_ids)
+
+ if stopped_ids:
+ ec2.get_waiter("instance_stopped").wait(InstanceIds=stopped_ids)
+ if terminated_ids:
+ ec2.get_waiter("instance_terminated").wait(InstanceIds=terminated_ids)
+
+ return InstancesOfStatus(
+ qty=total_qty,
+ all_ids=instance_ids,
+ running_ids=running_ids,
+ stopped_ids=stopped_ids,
+ terminated_ids=terminated_ids,
+ )
+
+
+@patch("instance_scheduler.service.ec2.EC2SSMMaintenanceWindows")
+def test_get_schedulable_instances(mock_mw: MagicMock, moto_ec2: None) -> None:
+ service_args = mock_service_args()
+ service_args["scheduling_context"] = replace(
+ service_args["scheduling_context"], enable_ssm_maintenance_windows=True
+ )
+ service: Final = Ec2Service(service_args)
+ assert service.get_schedulable_instances() == []
+
+ ec2: Final[EC2Client] = boto3.client("ec2")
+ instance_type: Final[InstanceTypeType] = "m6g.medium"
+ instances = create_instances_of_status(
+ ec2, instance_type=instance_type, qty_running=6, qty_stopped=2, qty_terminated=2
+ )
+
+ hibernated_instance_ids: Final = instances.running_ids[0:2]
+ untagged_instance_ids: Final = instances.running_ids[2:4]
+
+ schedule_tag_key = service_args["scheduling_context"].tag_name
+ for instance_id in instances.all_ids:
+ schedule_name = f"{instance_id}-schedule"
+ hibernate = instance_id in hibernated_instance_ids
+ service_args["scheduling_context"].schedules[schedule_name] = InstanceSchedule(
+ schedule_name, hibernate=hibernate
+ )
+ tags: list[TagTypeDef] = [
+ {"Key": "Name", "Value": f"{instance_id}-name"},
+ ]
+ if instance_id not in untagged_instance_ids:
+ tags.append({"Key": schedule_tag_key, "Value": schedule_name})
+ ec2.create_tags(Resources=[instance_id], Tags=tags)
+
+ instance_with_maintenance_window = instances.running_ids[0]
+ schedule_name = f"{instance_with_maintenance_window}-schedule"
+ maintenance_window_name = f"{instance_with_maintenance_window}-mw"
+ service_args["scheduling_context"].schedules[
+ schedule_name
+ ].use_maintenance_window = True
+ service_args["scheduling_context"].schedules[
+ schedule_name
+ ].ssm_maintenance_window = maintenance_window_name
+ maintenance_window_schedule = InstanceSchedule(maintenance_window_name)
+ mock_mw.return_value.ssm_maintenance_windows.return_value = {
+ maintenance_window_name: maintenance_window_schedule
+ }
+
+ result = service.get_schedulable_instances()
+
+ assert len(result) == instances.qty - len(untagged_instance_ids) - len(
+ instances.terminated_ids
+ )
+
+ schedulable_instances = {instance["id"]: instance for instance in result}
+
+ for instance_id, instance in schedulable_instances.items():
+ assert instance["id"] == instance_id
+ assert "arn" not in instance
+ assert instance["allow_resize"]
+ name = f"{instance_id}-name"
+ assert instance["name"] == name
+ assert instance["instancetype"] == instance_type
+ assert "engine_type" not in instance
+ schedule_name = f"{instance_id}-schedule"
+ assert instance["schedule_name"] == schedule_name
+ assert instance["tags"] == {schedule_tag_key: schedule_name, "Name": name}
+ assert not instance["resized"]
+ assert "is_cluster" not in instance
+ assert "account" not in instance
+ assert "region" not in instance
+ assert "service" not in instance
+ assert "instance_str" not in instance
+
+ if instance_id != instance_with_maintenance_window:
+ assert instance["maintenance_window"] is None
+
+ for instance_id in instances.running_ids:
+ if instance_id not in untagged_instance_ids:
+ instance = schedulable_instances[instance_id]
+ assert instance["state"] == EC2StateCode.RUNNING
+ assert instance["state_name"] == "running"
+ assert instance["is_running"]
+ assert not instance["is_terminated"]
+ assert instance["current_state"] == "running"
+
+ assert instance["hibernate"] == bool(instance_id in hibernated_instance_ids)
+
+ assert (
+ schedulable_instances[instance_with_maintenance_window]["maintenance_window"]
+ is maintenance_window_schedule
+ )
+
+ for instance_id in instances.stopped_ids:
+ instance = schedulable_instances[instance_id]
+ assert instance["state"] == EC2StateCode.STOPPED
+ assert instance["state_name"] == "stopped"
+ assert not instance["is_running"]
+ assert not instance["is_terminated"]
+ assert instance["current_state"] == "stopped"
+ assert not instance["hibernate"]
+
+ for instance_id in chain(instances.terminated_ids, untagged_instance_ids):
+ assert instance_id not in schedulable_instances
+
+
+def instance_data_from(
+ *,
+ instance_id: str,
+ instance_state: InstanceStateNameType,
+ instance_type: InstanceTypeType,
+) -> Instance:
+ if instance_state not in {"running", "stopped"}:
+ raise ValueError(f"Unimplemented instance data conversion: {instance_state}")
+ running: Final = instance_state == "running"
+ state_code: Final = EC2StateCode.RUNNING if running else EC2StateCode.STOPPED
+ schedule_state: Final[ScheduleState] = "running" if running else "stopped"
+ return Instance(
+ id=instance_id,
+ allow_resize=True,
+ hibernate=False,
+ state=state_code,
+ state_name=instance_state,
+ is_running=running,
+ is_terminated=False,
+ current_state=schedule_state,
+ instancetype=instance_type,
+ maintenance_window=None,
+ tags={},
+ name="",
+ schedule_name=None,
+ )
+
+
+def test_resize_instance(moto_ec2: None) -> None:
+ ec2: Final[EC2Client] = boto3.client("ec2")
+ instance_type: Final[InstanceTypeType] = "m6g.medium"
+ instances = create_instances_of_status(
+ ec2, instance_type=instance_type, qty_running=1
+ )
+
+ instance_id = instances.all_ids[0]
+ instance = instance_data_from(
+ instance_id=instance_id, instance_state="running", instance_type=instance_type
+ )
+ new_instance_type: Final[InstanceTypeType] = "m6g.12xlarge"
+
+ service: Final = Ec2Service(mock_service_args())
+ service.resize_instance(instance, new_instance_type)
+
+ assert (
+ ec2.describe_instances(InstanceIds=[instance_id])["Reservations"][0][
+ "Instances"
+ ][0]["InstanceType"]
+ == new_instance_type
+ )
+
+
+def test_start_instances(moto_ec2: None) -> None:
+ ec2: Final[EC2Client] = boto3.client("ec2")
+ instance_type: Final[InstanceTypeType] = "m6g.xlarge"
+ instances = create_instances_of_status(
+ ec2, instance_type=instance_type, qty_stopped=7
+ )
+
+ service: Final = Ec2Service(mock_service_args())
+ assert list(service.start_instances([])) == []
+
+ instances_to_start: list[Instance] = []
+ for instance_id in instances.stopped_ids:
+ instances_to_start.append(
+ instance_data_from(
+ instance_id=instance_id,
+ instance_state="stopped",
+ instance_type=instance_type,
+ )
+ )
+
+ result = list(service.start_instances(instances_to_start))
+ instance_results: Final = {instance_id: status for (instance_id, status) in result}
+
+ for instance_id in instances.stopped_ids:
+ assert instance_results[instance_id] == "running"
+
+ ec2.get_waiter("instance_running").wait(InstanceIds=instances.stopped_ids)
+
+ statuses = ec2.describe_instance_status(InstanceIds=instances.stopped_ids)
+ for status in statuses["InstanceStatuses"]:
+ assert status["InstanceState"]["Name"] == "running"
+
+
+def test_start_instances_with_errors(moto_ec2: None) -> None:
+ ec2: Final[EC2Client] = boto3.client("ec2")
+ instance_type: Final[InstanceTypeType] = "m6g.xlarge"
+ instances = create_instances_of_status(
+ ec2, instance_type=instance_type, qty_stopped=100
+ )
+
+ service: Final = Ec2Service(mock_service_args())
+
+ instances_to_start: list[Instance] = []
+ for instance_id in instances.stopped_ids:
+ instances_to_start.append(
+ instance_data_from(
+ instance_id=instance_id,
+ instance_state="stopped",
+ instance_type=instance_type,
+ )
+ )
+ # add a duplicate Instance with a bad identifier, interleaved
+ bad_instance_id = "id-bad" + instance_id[6:]
+ instances_to_start.append(
+ instance_data_from(
+ instance_id=bad_instance_id,
+ instance_state="stopped",
+ instance_type=instance_type,
+ )
+ )
+
+ result = list(service.start_instances(instances_to_start))
+ instance_results: Final = {instance_id: status for (instance_id, status) in result}
+
+ for instance_id in instances.stopped_ids:
+ assert instance_results[instance_id] == "running"
+
+ ec2.get_waiter("instance_running").wait(InstanceIds=instances.stopped_ids)
+
+ statuses = ec2.describe_instance_status(InstanceIds=instances.stopped_ids)
+ for status in statuses["InstanceStatuses"]:
+ assert status["InstanceState"]["Name"] == "running"
+
+
+def test_stop_instances(moto_ec2: None) -> None:
+ ec2: Final[EC2Client] = boto3.client("ec2")
+ instance_type: Final[InstanceTypeType] = "m6g.large"
+ instances = create_instances_of_status(
+ ec2, instance_type=instance_type, qty_running=52
+ )
+
+ service: Final = Ec2Service(mock_service_args())
+ assert list(service.stop_instances([])) == []
+
+ instances_to_stop: list[Instance] = []
+ for instance_id in instances.running_ids:
+ instances_to_stop.append(
+ instance_data_from(
+ instance_id=instance_id,
+ instance_state="running",
+ instance_type=instance_type,
+ )
+ )
+
+ result = list(service.stop_instances(instances_to_stop))
+ instance_results: Final = {instance_id: status for (instance_id, status) in result}
+
+ for instance_id in instances.running_ids:
+ assert instance_results[instance_id] == "stopped"
+
+ ec2.get_waiter("instance_stopped").wait(InstanceIds=instances.running_ids)
+
+ statuses = ec2.describe_instance_status(InstanceIds=instances.running_ids)
+ for status in statuses["InstanceStatuses"]:
+ assert status["InstanceState"]["Name"] == "stopped"
+
+
+def test_stop_instances_with_errors(moto_ec2: None) -> None:
+ ec2: Final[EC2Client] = boto3.client("ec2")
+ instance_type: Final[InstanceTypeType] = "m6g.large"
+ instances = create_instances_of_status(
+ ec2, instance_type=instance_type, qty_running=52
+ )
+
+ service: Final = Ec2Service(mock_service_args())
+
+ instances_to_stop: list[Instance] = []
+ for instance_id in instances.running_ids:
+ instances_to_stop.append(
+ instance_data_from(
+ instance_id=instance_id,
+ instance_state="stopped",
+ instance_type=instance_type,
+ )
+ )
+ # add a duplicate Instance with a bad identifier, after good instances
+ for instance_id in instances.running_ids:
+ bad_instance_id = "id-bad" + instance_id[6:]
+ instances_to_stop.append(
+ instance_data_from(
+ instance_id=bad_instance_id,
+ instance_state="stopped",
+ instance_type=instance_type,
+ )
+ )
+
+ result = list(service.stop_instances(instances_to_stop))
+ instance_results: Final = {instance_id: status for (instance_id, status) in result}
+
+ for instance_id in instances.running_ids:
+ assert instance_results[instance_id] == "stopped"
+
+ ec2.get_waiter("instance_stopped").wait(InstanceIds=instances.running_ids)
+
+ statuses = ec2.describe_instance_status(InstanceIds=instances.running_ids)
+ for status in statuses["InstanceStatuses"]:
+ assert status["InstanceState"]["Name"] == "stopped"
diff --git a/source/app/tests/test_enforce_headers.py b/source/app/tests/test_enforce_headers.py
index c0baef6f..9d26f3f2 100644
--- a/source/app/tests/test_enforce_headers.py
+++ b/source/app/tests/test_enforce_headers.py
@@ -1,7 +1,10 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
+from collections.abc import Iterator
+from os import scandir
+from pathlib import Path
-import pathlib
+optional_shebang = "#!/usr/bin/env python"
header_lines = [
"# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.",
@@ -9,12 +12,36 @@
]
+def valid_header(path: Path) -> bool:
+ header_length = len(header_lines)
+ lines = []
+ with open(path) as f:
+ for _ in range(header_length + 1):
+ lines.append(f.readline())
+ line_index = 0
+ if lines[0].strip() == optional_shebang:
+ line_index = 1
+ for header_line in header_lines:
+ if lines[line_index].strip() != header_line:
+ return False
+ line_index += 1
+ return True
+
+
+exclude_dirs = {".tox", ".mypy_cache"}
+
+
+def python_source_files(path: str) -> Iterator[Path]:
+ for file in Path(path).glob("*.py"):
+ if file.stat().st_size > 0:
+ yield file
+ for entry in scandir(path):
+ if entry.is_dir() and entry.name not in exclude_dirs:
+ yield from python_source_files(entry.path)
+
+
def test_headers_exist() -> None:
- for path in pathlib.Path(".").glob("**/*.py"):
- if path.stat().st_size > 0:
- with open(path) as f:
- print(path)
- for line in header_lines:
- assert (
- f.readline().strip() == line
- ), f"{path} does not contain a valid copyright header"
+ for file_path in python_source_files("."):
+ assert valid_header(
+ file_path
+ ), f"{file_path} does not contain a valid copyright header"
diff --git a/source/app/tests/test_main.py b/source/app/tests/test_main.py
index fb26b1db..9717a448 100644
--- a/source/app/tests/test_main.py
+++ b/source/app/tests/test_main.py
@@ -1,23 +1,57 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-from unittest.mock import patch
-
-from instance_scheduler.main import lambda_handler
+from unittest.mock import MagicMock, patch
+from aws_lambda_powertools.utilities.typing import LambdaContext
-class MockContext:
- def __init__(self):
- self.log_group_name = "My log group"
+from instance_scheduler import main
+from instance_scheduler.handler.collect_configuration_description import (
+ CollectConfigurationDescription,
+ CollectConfigurationMetricsRequest,
+)
+from instance_scheduler.handler.scheduling_orchestrator import (
+ OrchestrationRequest,
+ SchedulingOrchestratorHandler,
+)
+from instance_scheduler.main import lambda_handler
+from instance_scheduler.util.logger import Logger
+from tests.context import MockLambdaContext
-@patch("instance_scheduler.main.SchedulerRequestHandler")
-def test_scheduler_request_handler_called(mock_handler):
- """SchedulerRequestHandler handle_request is called when is_handling_request is True"""
+def test_scheduling_request_handler_called() -> None:
+ mock_handler = MagicMock()
mock_handler.is_handling_request.return_value = True
my_response = "Everything's great!"
mock_handler.return_value.handle_request.return_value = my_response
- mock_handler.__name__ = "My handler name"
+ mock_handler.__name__ = "my-handler"
- assert lambda_handler({}, MockContext()) == my_response
+ with patch.object(main, "handlers", (mock_handler,)):
+ assert lambda_handler({}, LambdaContext()) == my_response
mock_handler.return_value.handle_request.assert_called_once()
+
+
+@patch.object(Logger, "client")
+@patch.object(SchedulingOrchestratorHandler, "handle_request")
+def test_orchestrator_event(
+ handle_request_method: MagicMock, logger_client: MagicMock
+) -> None:
+ event: OrchestrationRequest = {
+ "scheduled_action": "run_orchestrator",
+ }
+
+ lambda_handler(event, MockLambdaContext())
+ handle_request_method.assert_called_once()
+
+
+@patch.object(Logger, "client")
+@patch.object(CollectConfigurationDescription, "handle_request")
+def test_collect_metrics_event(
+ handle_request_method: MagicMock, logger_client: MagicMock
+) -> None:
+ event: CollectConfigurationMetricsRequest = {
+ "scheduled_action": "collect_configuration_metrics"
+ }
+
+ lambda_handler(event, MockLambdaContext())
+ handle_request_method.assert_called_once()
diff --git a/source/app/tests/test_utils/unordered_list.py b/source/app/tests/test_utils/unordered_list.py
new file mode 100644
index 00000000..1d9b179a
--- /dev/null
+++ b/source/app/tests/test_utils/unordered_list.py
@@ -0,0 +1,36 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from typing import Any, TypeVar
+
+T = TypeVar("T")
+
+
+class UnorderedList(list[T]):
+ """helper object for asserting unordered equals on lists"""
+
+ def __eq__(self, other: Any) -> bool:
+ if not isinstance(other, list):
+ return False
+
+ if len(self) != len(other):
+ return False
+
+ temp = other.copy()
+ for item in self:
+ try:
+ temp.remove(item)
+ except ValueError:
+ return False
+
+ return True
+
+ def __ne__(self, other: Any) -> bool:
+ return not self.__eq__(other)
+
+
+def test_matches_normally() -> None:
+ assert UnorderedList([1, 2, 3]) == UnorderedList([3, 2, 1])
+
+
+def test_not_fooled_by_duplicates() -> None:
+ assert UnorderedList([1, 2, 2]) != UnorderedList([3, 2, 1])
diff --git a/source/app/tests/util/__init__.py b/source/app/tests/util/__init__.py
new file mode 100644
index 00000000..04f8b7b7
--- /dev/null
+++ b/source/app/tests/util/__init__.py
@@ -0,0 +1,2 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
diff --git a/source/app/tests/util/test_app_env.py b/source/app/tests/util/test_app_env.py
new file mode 100644
index 00000000..0ecfa9cb
--- /dev/null
+++ b/source/app/tests/util/test_app_env.py
@@ -0,0 +1,188 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from dataclasses import replace
+from os import environ
+from typing import Optional
+from unittest.mock import patch
+from zoneinfo import ZoneInfo
+
+from pytest import fixture, raises
+
+import instance_scheduler.util.app_env
+from instance_scheduler.util.app_env import (
+ AppEnv,
+ AppEnvError,
+ _to_bool,
+ _to_list,
+ get_app_env,
+)
+
+
+@fixture(autouse=True)
+def reset_cached_env() -> None:
+ instance_scheduler.util.app_env._app_env = None
+
+
+def test_to_bool() -> None:
+ assert _to_bool("True")
+ assert _to_bool("true")
+ assert _to_bool("true ")
+ assert _to_bool("Yes")
+ assert _to_bool("yes")
+ assert _to_bool(" yes")
+
+ assert not _to_bool("")
+ assert not _to_bool("False")
+ assert not _to_bool("false")
+ assert not _to_bool("\tfalse\r\n")
+ assert not _to_bool("No")
+ assert not _to_bool("no")
+ assert not _to_bool("\tno")
+ assert not _to_bool("Anything else")
+
+
+def test_to_list() -> None:
+ assert _to_list("") == []
+
+ assert _to_list("a") == ["a"]
+ assert _to_list("a,b,c") == ["a", "b", "c"]
+
+ assert _to_list("foo,,bar") == ["foo", "bar"]
+ assert _to_list("foo, bar, ") == ["foo", "bar"]
+ assert _to_list(" , foo , bar, ") == ["foo", "bar"]
+
+
+def example_app_env() -> AppEnv:
+ return AppEnv(
+ scheduler_frequency_minutes=5,
+ log_group="my-log-group",
+ topic_arn="arn:aws:sns:us-east-1:123456789012:my-topic-arn",
+ stack_name="my-stack-name",
+ send_anonymous_metrics=False,
+ solution_id="my-solution-id",
+ solution_version="my-solution-version",
+ enable_debug_logging=True,
+ user_agent_extra="my-user-agent-extra",
+ anonymous_metrics_url="my-metrics-url",
+ stack_id="my-stack-id",
+ uuid_key="my-uuid-key",
+ start_ec2_batch_size=1,
+ schedule_tag_key="my-schedule-tag-key",
+ default_timezone=ZoneInfo("Asia/Tokyo"),
+ enable_cloudwatch_metrics=True,
+ enable_ec2_service=False,
+ enable_rds_service=True,
+ enable_rds_clusters=False,
+ enable_rds_snapshots=True,
+ schedule_regions=["us-east-1", "us-west-2"],
+ app_namespace="my-app-namespace",
+ scheduler_role_name="my-scheduler-role-name",
+ enable_schedule_hub_account=False,
+ enable_ec2_ssm_maintenance_windows=True,
+ start_tags=["my-first-start-tag", "my-second-start-tag"],
+ stop_tags=["my-stop-tag"],
+ enable_aws_organizations=False,
+ maintenance_window_table_name="my-maintenance-window-table",
+ config_table_name="my-config-table-name",
+ state_table_name="my-state-table-name",
+ )
+
+
+def env_from_app_env(app_env: AppEnv) -> dict[str, str]:
+ return {
+ "SCHEDULER_FREQUENCY": str(app_env.scheduler_frequency_minutes),
+ "LOG_GROUP": app_env.log_group,
+ "ISSUES_TOPIC_ARN": app_env.topic_arn,
+ "STACK_NAME": app_env.stack_name,
+ "SEND_METRICS": str(app_env.send_anonymous_metrics),
+ "SOLUTION_ID": app_env.solution_id,
+ "SOLUTION_VERSION": app_env.solution_version,
+ "TRACE": str(app_env.enable_debug_logging),
+ "USER_AGENT_EXTRA": app_env.user_agent_extra,
+ "METRICS_URL": app_env.anonymous_metrics_url,
+ "STACK_ID": app_env.stack_id,
+ "UUID_KEY": app_env.uuid_key,
+ "START_EC2_BATCH_SIZE": str(app_env.start_ec2_batch_size),
+ "SCHEDULE_TAG_KEY": app_env.schedule_tag_key,
+ "DEFAULT_TIMEZONE": str(app_env.default_timezone),
+ "ENABLE_CLOUDWATCH_METRICS": str(app_env.enable_cloudwatch_metrics),
+ "ENABLE_EC2_SERVICE": str(app_env.enable_ec2_service),
+ "ENABLE_RDS_SERVICE": str(app_env.enable_rds_service),
+ "ENABLE_RDS_CLUSTERS": str(app_env.enable_rds_clusters),
+ "ENABLE_RDS_SNAPSHOTS": str(app_env.enable_rds_snapshots),
+ "SCHEDULE_REGIONS": ", ".join(app_env.schedule_regions),
+ "APP_NAMESPACE": app_env.app_namespace,
+ "SCHEDULER_ROLE_NAME": app_env.scheduler_role_name,
+ "ENABLE_SCHEDULE_HUB_ACCOUNT": str(app_env.enable_schedule_hub_account),
+ "ENABLE_EC2_SSM_MAINTENANCE_WINDOWS": str(
+ app_env.enable_ec2_ssm_maintenance_windows
+ ),
+ "START_TAGS": ", ".join(app_env.start_tags),
+ "STOP_TAGS": ", ".join(app_env.stop_tags),
+ "ENABLE_AWS_ORGANIZATIONS": str(app_env.enable_aws_organizations),
+ "MAINTENANCE_WINDOW_TABLE": app_env.maintenance_window_table_name,
+ "CONFIG_TABLE": app_env.config_table_name,
+ "STATE_TABLE": app_env.state_table_name,
+ }
+
+
+def test_get_app_env() -> None:
+ expected_env = example_app_env()
+
+ app_env: Optional[AppEnv] = None
+ with patch.dict(environ, env_from_app_env(expected_env), clear=True):
+ app_env = get_app_env()
+ assert get_app_env() is app_env
+
+ assert app_env == expected_env
+
+
+def test_missing_key() -> None:
+ expected_env = example_app_env()
+ my_env = env_from_app_env(expected_env)
+
+ missing_key = "SCHEDULER_FREQUENCY"
+ del my_env[missing_key]
+
+ with patch.dict(environ, my_env, clear=True), raises(AppEnvError) as err:
+ get_app_env()
+
+ assert (
+ str(err.value)
+ == f"Missing required application environment variable: {missing_key}"
+ )
+
+
+def test_invalid_timezone() -> None:
+ expected_env = example_app_env()
+ my_env = env_from_app_env(expected_env)
+
+ invalid_timezone = "something_invalid"
+ my_env["DEFAULT_TIMEZONE"] = invalid_timezone
+
+ with patch.dict(environ, my_env, clear=True), raises(AppEnvError) as err:
+ get_app_env()
+
+ assert (
+ str(err.value)
+ == f"Invalid timezone: No time zone found with key {invalid_timezone}"
+ )
+
+
+def test_scheduled_services() -> None:
+ app_env = example_app_env()
+
+ app_env_ec2_enabled = replace(
+ app_env, enable_ec2_service=True, enable_rds_service=False
+ )
+ assert set(app_env_ec2_enabled.scheduled_services()) == {"ec2"}
+
+ app_env_rds_enabled = replace(
+ app_env, enable_ec2_service=False, enable_rds_service=True
+ )
+ assert set(app_env_rds_enabled.scheduled_services()) == {"rds"}
+
+ app_env_both_enabled = replace(
+ app_env, enable_ec2_service=True, enable_rds_service=True
+ )
+ assert set(app_env_both_enabled.scheduled_services()) == {"ec2", "rds"}
diff --git a/source/app/tests/util/test_batch.py b/source/app/tests/util/test_batch.py
new file mode 100644
index 00000000..2a568b70
--- /dev/null
+++ b/source/app/tests/util/test_batch.py
@@ -0,0 +1,109 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import operator
+from collections.abc import Callable
+from functools import reduce
+from typing import Final, TypeVar
+from unittest.mock import MagicMock, call
+
+from instance_scheduler.util.batch import FailureResponse, bisect_retry
+
+T = TypeVar("T")
+
+
+def create_action_failing_on_inputs(
+ failing_inputs: frozenset[T],
+) -> Callable[[list[T]], None]:
+ def action_failing_on_inputs(inputs: list[T]) -> None:
+ for item in inputs:
+ if item in failing_inputs:
+ raise ValueError(item)
+
+ return action_failing_on_inputs
+
+
+action_not_failing: Final = MagicMock(
+ side_effect=create_action_failing_on_inputs(frozenset())
+)
+
+
+def test_bisect_retry_no_inputs_not_called() -> None:
+ bisect_retry([], action_not_failing)
+ action_not_failing.assert_not_called()
+
+
+def test_bisect_retry_no_errors_called_once() -> None:
+ inputs: Final = [[0], list(range(2)), list(range(1000))]
+ for example in inputs:
+ action_not_failing.reset_mock()
+ bisect_retry(example, action_not_failing)
+ action_not_failing.assert_called_once_with(example)
+
+
+def test_bisect_retry_single_error() -> None:
+ failing_input: Final = 2
+ action_fail_single: Final = MagicMock(
+ side_effect=create_action_failing_on_inputs(frozenset([failing_input]))
+ )
+
+ # single failing input called once, failure response
+ result = bisect_retry([failing_input], action_fail_single)
+ assert len(result) == 1
+ assert result[0].failed_input == failing_input
+ assert isinstance(result[0].error, ValueError)
+ action_fail_single.assert_called_once_with([failing_input])
+ action_fail_single.reset_mock()
+
+ # one bad input out of three, should split
+ result = bisect_retry([2, 3, 4], action_fail_single)
+ assert len(result) == 2
+ assert result[0].failed_input == failing_input
+ assert isinstance(result[0].error, ValueError)
+ assert action_fail_single.call_count == 3
+ action_fail_single.assert_has_calls([call([2, 3, 4]), call([2]), call([3, 4])])
+ action_fail_single.reset_mock()
+
+ # one bad input out of ten, should split multiple times
+ result = bisect_retry(list(range(10)), action_fail_single)
+ assert len(result) == 4
+ assert result[1].failed_input == failing_input
+ assert isinstance(result[1].error, ValueError)
+ assert action_fail_single.call_count == 7
+ action_fail_single.assert_has_calls(
+ [
+ call([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
+ call([0, 1, 2, 3, 4]),
+ call([0, 1]),
+ call([2, 3, 4]),
+ call([2]),
+ call([3, 4]),
+ call([5, 6, 7, 8, 9]),
+ ]
+ )
+
+
+def test_bisect_retry_many_errors() -> None:
+ input_size: Final = 10000
+ failing_inputs: Final = range(0, input_size, 2)
+ action_fail_even: Final = MagicMock(
+ side_effect=create_action_failing_on_inputs(frozenset(failing_inputs))
+ )
+
+ inputs: Final = list(range(input_size))
+ result = bisect_retry(inputs, action_fail_even)
+
+ # half failure responses, half success responses (None)
+ assert len(result) == input_size
+ # expected sum if all failing inputs are represented in failure responses
+ expected_sum: Final = reduce(operator.add, failing_inputs)
+ actual_sum = 0
+ for item in result:
+ if isinstance(item, FailureResponse):
+ actual_sum += item.failed_input
+ assert isinstance(item.error, ValueError)
+ else:
+ assert item is None
+ assert actual_sum == expected_sum
+
+ # \sum_{i=0}^{log_2(n)} 2^i = 2n-1
+ assert action_fail_even.call_count == 2 * input_size - 1
diff --git a/source/app/tests/util/test_display_helper.py b/source/app/tests/util/test_display_helper.py
new file mode 100644
index 00000000..03ce5524
--- /dev/null
+++ b/source/app/tests/util/test_display_helper.py
@@ -0,0 +1,29 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+import string
+
+from instance_scheduler.util.display_helper import set_str
+
+characters = string.ascii_lowercase
+names = [c * 3 for c in characters]
+
+
+def test_set_str() -> None:
+ sep_item = ","
+ sep_range = "-"
+ # single item
+ assert set_str({0}, names) == names[0]
+ # two items
+ assert set_str({0, 3}, names) == names[0] + sep_item + names[3]
+ # range
+ assert set_str({0, 1, 2, 3, 4}, names) == names[0] + sep_range + names[4]
+ # range and item
+ assert (
+ set_str({0, 1, 2, 4}, names)
+ == names[0] + sep_range + names[2] + sep_item + names[4]
+ )
+ # two ranges
+ assert (
+ set_str({0, 1, 3, 4}, names)
+ == names[0] + sep_range + names[1] + sep_item + names[3] + sep_range + names[4]
+ )
diff --git a/source/app/tests/util/test_global_config.py b/source/app/tests/util/test_global_config.py
new file mode 100644
index 00000000..2c47558d
--- /dev/null
+++ b/source/app/tests/util/test_global_config.py
@@ -0,0 +1,47 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from datetime import time
+from zoneinfo import ZoneInfo
+
+from instance_scheduler.configuration.instance_schedule import InstanceSchedule
+from instance_scheduler.configuration.running_period import RunningPeriod
+from instance_scheduler.configuration.running_period_dict_element import (
+ RunningPeriodDictElement,
+)
+from instance_scheduler.configuration.scheduler_config import GlobalConfig
+
+
+def sample_global_config() -> GlobalConfig:
+ return GlobalConfig(
+ scheduled_services=["ec2"],
+ schedule_clusters=False,
+ tag_name="Schedule",
+ regions=[],
+ default_timezone=ZoneInfo("UTC"),
+ schedules={
+ "test-schedule": InstanceSchedule(
+ name="test-schedule",
+ periods=[
+ RunningPeriodDictElement(
+ period=RunningPeriod(
+ name="test-period",
+ begintime=time(10, 0, 0),
+ endtime=time(20, 0, 0),
+ )
+ )
+ ],
+ )
+ },
+ trace=False,
+ enable_ssm_maintenance_windows=False,
+ use_metrics=False,
+ schedule_lambda_account=True,
+ create_rds_snapshot=False,
+ started_tags="",
+ stopped_tags="",
+ scheduler_role_name="Scheduler-Role",
+ namespace="dev",
+ organization_id="",
+ aws_partition="aws",
+ remote_account_ids=[],
+ )
diff --git a/source/app/tests/util/test_init.py b/source/app/tests/util/test_init.py
new file mode 100644
index 00000000..d84b579b
--- /dev/null
+++ b/source/app/tests/util/test_init.py
@@ -0,0 +1,20 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from datetime import datetime
+from unittest.mock import MagicMock, patch
+
+from instance_scheduler.util import get_boto_config, safe_json
+from instance_scheduler.util.app_env import AppEnv
+
+
+def test_safe_json() -> None:
+ safe_json(datetime.now())
+
+
+@patch("instance_scheduler.util._Config")
+def test_get_config(mock_config: MagicMock, app_env: AppEnv) -> None:
+ get_boto_config()
+ mock_config.assert_called_once_with(
+ user_agent_extra=app_env.user_agent_extra,
+ retries={"max_attempts": 5, "mode": "standard"},
+ )
diff --git a/source/app/tests/util/test_time.py b/source/app/tests/util/test_time.py
new file mode 100644
index 00000000..9d98814e
--- /dev/null
+++ b/source/app/tests/util/test_time.py
@@ -0,0 +1,13 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from datetime import datetime, timezone
+from zoneinfo import ZoneInfo
+
+from instance_scheduler.util.time import is_aware
+
+
+def test_is_aware() -> None:
+ assert is_aware(datetime(year=2023, month=6, day=23, tzinfo=timezone.utc))
+ assert is_aware(datetime(year=2023, month=6, day=23, tzinfo=ZoneInfo("Asia/Tokyo")))
+
+ assert not is_aware(datetime(year=2023, month=6, day=23))
diff --git a/source/app/tox.ini b/source/app/tox.ini
new file mode 100644
index 00000000..1df5a1a5
--- /dev/null
+++ b/source/app/tox.ini
@@ -0,0 +1,40 @@
+; Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+; SPDX-License-Identifier: Apache-2.0
+[tox]
+env_list = format, lint, py310-report, py311-noreport
+minversion = 4.0.13
+isolated_build = true
+
+[testenv:format]
+skip_install = true
+deps =
+ black
+ isort
+commands =
+ isort --profile black --check .
+ black --check .
+
+[flake8]
+extend-ignore =
+ # line length, handled by black
+ E501,
+ # whitespace, handled by black
+ E203,
+
+[testenv:lint]
+allowlist_externals = poetry
+deps = poetry
+commands_pre = poetry install
+commands =
+ poetry run mypy .
+ poetry run flake8 .
+
+[testenv:py3{10,11}-{report, noreport}]
+allowlist_externals = poetry
+deps = poetry
+pass_env = PYTHON_VERSION
+package = skip
+commands_pre = poetry install
+commands =
+ report: poetry run pytest -n auto tests/ {posargs}
+ noreport: poetry run pytest -n auto tests/
diff --git a/source/cli/.coveragerc b/source/cli/.coveragerc
new file mode 100644
index 00000000..a652f617
--- /dev/null
+++ b/source/cli/.coveragerc
@@ -0,0 +1,7 @@
+[run]
+branch = true
+source = instance_scheduler_cli
+
+[report]
+exclude_lines =
+ if TYPE_CHECKING:
diff --git a/source/cli/instance-scheduler-cli-runner.py b/source/cli/instance-scheduler-cli-runner.py
deleted file mode 100755
index 85edccbc..00000000
--- a/source/cli/instance-scheduler-cli-runner.py
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-# SPDX-License-Identifier: Apache-2.0
-
-
-#!/usr/bin/env python
-
-"""Convenience wrapper for running instance-scheduler-cli directly."""
-
-from instance_scheduler_cli.scheduler_cli import main
-
-if __name__ == "__main__":
- main()
diff --git a/source/cli/instance_scheduler_cli/__init__.py b/source/cli/instance_scheduler_cli/__init__.py
index 91764e29..5766d9e6 100644
--- a/source/cli/instance_scheduler_cli/__init__.py
+++ b/source/cli/instance_scheduler_cli/__init__.py
@@ -1,7 +1,7 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
+from importlib.metadata import version
+__version__ = version(__package__)
-from importlib import metadata
-
-__version__ = metadata.version("instance_scheduler_cli")
+del version
diff --git a/source/cli/instance_scheduler_cli/__main__.py b/source/cli/instance_scheduler_cli/__main__.py
index 8034b665..27225459 100644
--- a/source/cli/instance_scheduler_cli/__main__.py
+++ b/source/cli/instance_scheduler_cli/__main__.py
@@ -1,7 +1,18 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
+import sys
+from instance_scheduler_cli.scheduler_cli import build_parser
-from scheduler_cli import main
-main()
+def main() -> int:
+ parser = build_parser()
+ if len(sys.argv) == 1:
+ parser.print_help()
+ return 0
+ else:
+ p = parser.parse_args(sys.argv[1:])
+ return int(p.func(p, p.command))
+
+
+sys.exit(main())
diff --git a/source/cli/instance_scheduler_cli/scheduler_cli.py b/source/cli/instance_scheduler_cli/scheduler_cli.py
index 30c4691c..86ea750e 100644
--- a/source/cli/instance_scheduler_cli/scheduler_cli.py
+++ b/source/cli/instance_scheduler_cli/scheduler_cli.py
@@ -1,13 +1,13 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-
-
import argparse
import json
-import sys
+from argparse import ArgumentParser
+from typing import TYPE_CHECKING, Any, Literal, Optional, Union
import boto3
import jmespath
+
from instance_scheduler_cli import __version__
EVENT_SOURCE = "scheduler.cli"
@@ -23,7 +23,6 @@
)
HELP_CMD_UPDATE_PERIOD = "Updates a period"
HELP_CMD_UPDATE_SCHEDULE = "Updates a schedule"
-CMD_HELP_VERSION = "Show version"
HELP_ENDDATE = "End time of the period in format yyyymmdd, default is today"
HELP_NAME_SCHEDULE = "Name of the schedule"
@@ -110,30 +109,38 @@
PARAM_NAME = "--name"
+if TYPE_CHECKING:
+ from mypy_boto3_cloudformation.client import CloudFormationClient
+ from mypy_boto3_lambda.client import LambdaClient
+else:
+ CloudFormationClient = object
+ LambdaClient = object
-def _service_client(service, region=None, profile_name=None):
+
+def _service_client(
+ service: Union[Literal["cloudformation"], Literal["lambda"]],
+ region: Optional[str] = None,
+ profile_name: Optional[str] = None,
+) -> Any:
session = (
boto3.Session()
if profile_name is None
else boto3.Session(profile_name=profile_name)
)
- args = {"service_name": service}
- if region is not None:
- args["region_name"] = region
- return session.client(**args)
+ return session.client(service_name=service, region_name=region)
-def handle_command(args, command):
+def handle_command(args: Any, command: str) -> int:
try:
- cloudformation_client = _service_client(
+ cloudformation_client: CloudFormationClient = _service_client(
"cloudformation", region=args.region, profile_name=args.profile_name
)
lambda_resource = cloudformation_client.describe_stack_resource(
StackName=args.stack, LogicalResourceId="Main"
- ).get("StackResourceDetail", None)
+ )["StackResourceDetail"]
- lambda_client = _service_client(
+ lambda_client: LambdaClient = _service_client(
"lambda", region=args.region, profile_name=args.profile_name
)
@@ -184,8 +191,8 @@ def handle_command(args, command):
return 1
-def build_parser():
- def add_common_arguments(parser):
+def build_parser() -> ArgumentParser:
+ def add_common_arguments(parser: ArgumentParser) -> None:
parser.add_argument(PARAM_QUERY, PARAM_QUERY[1:3], help=HELP_QUERY)
parser.add_argument(PARAM_REGION, PARAM_REGION[1:3], help=HELP_REGION)
parser.add_argument(
@@ -198,7 +205,7 @@ def add_common_arguments(parser):
help=HELP_PROFILE_NAME,
)
- def add_period_arguments(period_parser):
+ def add_period_arguments(period_parser: ArgumentParser) -> None:
period_parser.add_argument(PARAM_BEGINTIME, help=HELP_PERIOD_BEGINTIME)
period_parser.add_argument(PARAM_DESCRIPTION, help=HELP_PERIOD_DESCRIPTION)
period_parser.add_argument(PARAM_ENDTIME, help=HELP_PERIOD_ENDTIME)
@@ -207,7 +214,7 @@ def add_period_arguments(period_parser):
period_parser.add_argument(PARAM_NAME, required=True, help=HELP_PERIOD_NAME)
period_parser.add_argument(PARAM_WEEKDAYS, help=HELP_PERIOD_WEEKDAYS)
- def add_schedule_arguments(schedule_parser):
+ def add_schedule_arguments(schedule_parser: ArgumentParser) -> None:
schedule_parser.add_argument(PARAM_DESCRIPTION, help=HELP_SCHEDULE_DESCRIPTION)
schedule_parser.add_argument(PARAM_TIMEZONE, help=HELP_PARAM_TIMEZONE)
schedule_parser.add_argument(PARAM_NAME, required=True, help=HELP_SCHEDULE_NAME)
@@ -273,7 +280,7 @@ def add_schedule_arguments(schedule_parser):
help=HELP_SCHEDULE_CLOUDWATCH_METRICS,
)
- def build_describe_schedules_parser():
+ def build_describe_schedules_parser() -> None:
sub_parser = subparsers.add_parser(
CMD_DESCRIBE_SCHEDULES, help=HELP_CMD_DESCRIBE_SCHEDULES
)
@@ -281,7 +288,7 @@ def build_describe_schedules_parser():
add_common_arguments(sub_parser)
sub_parser.set_defaults(func=handle_command, command=CMD_DESCRIBE_SCHEDULES)
- def build_describe_periods_parser():
+ def build_describe_periods_parser() -> None:
sub_parser = subparsers.add_parser(
CMD_DESCRIBE_PERIODS, help=HELP_CMD_DESCRIBE_PERIODS
)
@@ -289,7 +296,7 @@ def build_describe_periods_parser():
add_common_arguments(sub_parser)
sub_parser.set_defaults(func=handle_command, command=CMD_DESCRIBE_PERIODS)
- def build_create_period_parser():
+ def build_create_period_parser() -> None:
sub_parser = subparsers.add_parser(
CMD_CREATE_PERIOD, help=HELP_CMD_CREATE_PERIOD
)
@@ -297,7 +304,7 @@ def build_create_period_parser():
add_common_arguments(sub_parser)
sub_parser.set_defaults(func=handle_command, command=CMD_CREATE_PERIOD)
- def build_create_schedule_parser():
+ def build_create_schedule_parser() -> None:
sub_parser = subparsers.add_parser(
CMD_CREATE_SCHEDULE, help=HELP_CMD_CREATE_SCHEDULE
)
@@ -305,7 +312,7 @@ def build_create_schedule_parser():
add_common_arguments(sub_parser)
sub_parser.set_defaults(func=handle_command, command=CMD_CREATE_SCHEDULE)
- def build_update_period_parser():
+ def build_update_period_parser() -> None:
sub_parser = subparsers.add_parser(
CMD_UPDATE_PERIOD, help=HELP_CMD_UPDATE_PERIOD
)
@@ -313,7 +320,7 @@ def build_update_period_parser():
add_common_arguments(sub_parser)
sub_parser.set_defaults(func=handle_command, command=CMD_UPDATE_PERIOD)
- def build_update_schedule_parser():
+ def build_update_schedule_parser() -> None:
sub_parser = subparsers.add_parser(
CMD_UPDATE_SCHEDULE, help=HELP_CMD_UPDATE_SCHEDULE
)
@@ -321,7 +328,7 @@ def build_update_schedule_parser():
add_common_arguments(sub_parser)
sub_parser.set_defaults(func=handle_command, command=CMD_UPDATE_SCHEDULE)
- def build_delete_period_parser():
+ def build_delete_period_parser() -> None:
sub_parser = subparsers.add_parser(
CMD_DELETE_PERIOD, help=HELP_CMD_DELETE_PERIOD
)
@@ -329,7 +336,7 @@ def build_delete_period_parser():
add_common_arguments(sub_parser)
sub_parser.set_defaults(func=handle_command, command=CMD_DELETE_PERIOD)
- def build_delete_schedule_parser():
+ def build_delete_schedule_parser() -> None:
sub_parser = subparsers.add_parser(
CMD_DELETE_SCHEDULE, help=HELP_CMD_DELETE_SCHEDULE
)
@@ -337,7 +344,7 @@ def build_delete_schedule_parser():
add_common_arguments(sub_parser)
sub_parser.set_defaults(func=handle_command, command=CMD_DELETE_SCHEDULE)
- def build_describe_schedule_usage_parser():
+ def build_describe_schedule_usage_parser() -> None:
sub_parser = subparsers.add_parser(
CMD_DESCRIBE_SCHEDULE_USAGE, help=HELP_CMD_SCHEDULE_DESCRIBE_USAGE
)
@@ -368,13 +375,3 @@ def build_describe_schedule_usage_parser():
build_update_schedule_parser()
return new_parser
-
-
-def main():
- parser = build_parser()
- if len(sys.argv) == 1: # no args
- parser.print_help()
- sys.exit(0)
- else:
- p = parser.parse_args(sys.argv[1:])
- sys.exit(p.func(p, p.command))
diff --git a/source/cli/mypy.ini b/source/cli/mypy.ini
new file mode 100644
index 00000000..b8a44f83
--- /dev/null
+++ b/source/cli/mypy.ini
@@ -0,0 +1,8 @@
+[mypy]
+strict = True
+
+[mypy-cli_test_helpers]
+ignore_missing_imports = True
+
+[mypy-moto]
+ignore_missing_imports = True
diff --git a/source/cli/poetry.lock b/source/cli/poetry.lock
index 105410c9..bdc9aecd 100644
--- a/source/cli/poetry.lock
+++ b/source/cli/poetry.lock
@@ -1,38 +1,87 @@
-# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand.
+# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand.
+
+[[package]]
+name = "attrs"
+version = "23.1.0"
+description = "Classes Without Boilerplate"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"},
+ {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"},
+]
+
+[package.extras]
+cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
+dev = ["attrs[docs,tests]", "pre-commit"]
+docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"]
+tests = ["attrs[tests-no-zope]", "zope-interface"]
+tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
+
+[[package]]
+name = "aws-sam-translator"
+version = "1.71.0"
+description = "AWS SAM Translator is a library that transform SAM templates into AWS CloudFormation templates"
+optional = false
+python-versions = ">=3.7, <=4.0, !=4.0"
+files = [
+ {file = "aws-sam-translator-1.71.0.tar.gz", hash = "sha256:a3ea80aeb116d7978b26ac916d2a5a24d012b742bf28262b17769c4b886e8fba"},
+ {file = "aws_sam_translator-1.71.0-py3-none-any.whl", hash = "sha256:17fb87c8137d8d49e7a978396b2b3b279211819dee44618415aab1e99c2cb659"},
+]
+
+[package.dependencies]
+boto3 = ">=1.19.5,<2.dev0"
+jsonschema = ">=3.2,<5"
+pydantic = ">=1.8,<2.0"
+typing-extensions = ">=4.4,<5"
+
+[package.extras]
+dev = ["black (==23.1.0)", "boto3 (>=1.23,<2)", "boto3-stubs[appconfig,serverlessrepo] (>=1.19.5,<2.dev0)", "coverage (>=5.3,<8)", "dateparser (>=1.1,<2.0)", "importlib-metadata", "mypy (>=1.1.0,<1.2.0)", "parameterized (>=0.7,<1.0)", "pytest (>=6.2,<8)", "pytest-cov (>=2.10,<5)", "pytest-env (>=0.6,<1)", "pytest-rerunfailures (>=9.1,<12)", "pytest-xdist (>=2.5,<4)", "pyyaml (>=6.0,<7.0)", "requests (>=2.28,<3.0)", "ruamel.yaml (==0.17.21)", "ruff (==0.0.263)", "tenacity (>=8.0,<9.0)", "types-PyYAML (>=6.0,<7.0)", "types-jsonschema (>=3.2,<4.0)"]
+
+[[package]]
+name = "aws-xray-sdk"
+version = "2.12.0"
+description = "The AWS X-Ray SDK for Python (the SDK) enables Python developers to record and emit information from within their applications to the AWS X-Ray service."
+optional = false
+python-versions = "*"
+files = [
+ {file = "aws-xray-sdk-2.12.0.tar.gz", hash = "sha256:295afc237073a80956d7d4f27c31830edcb9a8ccca9ef8aa44990badef15e5b7"},
+ {file = "aws_xray_sdk-2.12.0-py2.py3-none-any.whl", hash = "sha256:30886e23cc2daadc1c06a76f25b071205e84848419d1ddf097b62a565e156542"},
+]
+
+[package.dependencies]
+botocore = ">=1.11.3"
+wrapt = "*"
[[package]]
name = "black"
-version = "23.3.0"
+version = "23.7.0"
description = "The uncompromising code formatter."
-category = "dev"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "black-23.3.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915"},
- {file = "black-23.3.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9"},
- {file = "black-23.3.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2"},
- {file = "black-23.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c"},
- {file = "black-23.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c"},
- {file = "black-23.3.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6"},
- {file = "black-23.3.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b"},
- {file = "black-23.3.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d"},
- {file = "black-23.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70"},
- {file = "black-23.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326"},
- {file = "black-23.3.0-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b"},
- {file = "black-23.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2"},
- {file = "black-23.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925"},
- {file = "black-23.3.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27"},
- {file = "black-23.3.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331"},
- {file = "black-23.3.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5"},
- {file = "black-23.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961"},
- {file = "black-23.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8"},
- {file = "black-23.3.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30"},
- {file = "black-23.3.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3"},
- {file = "black-23.3.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266"},
- {file = "black-23.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab"},
- {file = "black-23.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb"},
- {file = "black-23.3.0-py3-none-any.whl", hash = "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4"},
- {file = "black-23.3.0.tar.gz", hash = "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940"},
+ {file = "black-23.7.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:5c4bc552ab52f6c1c506ccae05681fab58c3f72d59ae6e6639e8885e94fe2587"},
+ {file = "black-23.7.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:552513d5cd5694590d7ef6f46e1767a4df9af168d449ff767b13b084c020e63f"},
+ {file = "black-23.7.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:86cee259349b4448adb4ef9b204bb4467aae74a386bce85d56ba4f5dc0da27be"},
+ {file = "black-23.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:501387a9edcb75d7ae8a4412bb8749900386eaef258f1aefab18adddea1936bc"},
+ {file = "black-23.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995"},
+ {file = "black-23.7.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2"},
+ {file = "black-23.7.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:893695a76b140881531062d48476ebe4a48f5d1e9388177e175d76234ca247cd"},
+ {file = "black-23.7.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a"},
+ {file = "black-23.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831d8f54c3a8c8cf55f64d0422ee875eecac26f5f649fb6c1df65316b67c8926"},
+ {file = "black-23.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:7f3bf2dec7d541b4619b8ce526bda74a6b0bffc480a163fed32eb8b3c9aed8ad"},
+ {file = "black-23.7.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f"},
+ {file = "black-23.7.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:01ede61aac8c154b55f35301fac3e730baf0c9cf8120f65a9cd61a81cfb4a0c3"},
+ {file = "black-23.7.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:327a8c2550ddc573b51e2c352adb88143464bb9d92c10416feb86b0f5aee5ff6"},
+ {file = "black-23.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1c6022b86f83b632d06f2b02774134def5d4d4f1dac8bef16d90cda18ba28a"},
+ {file = "black-23.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:27eb7a0c71604d5de083757fbdb245b1a4fae60e9596514c6ec497eb63f95320"},
+ {file = "black-23.7.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:8417dbd2f57b5701492cd46edcecc4f9208dc75529bcf76c514864e48da867d9"},
+ {file = "black-23.7.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:47e56d83aad53ca140da0af87678fb38e44fd6bc0af71eebab2d1f59b1acf1d3"},
+ {file = "black-23.7.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:25cc308838fe71f7065df53aedd20327969d05671bac95b38fdf37ebe70ac087"},
+ {file = "black-23.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:642496b675095d423f9b8448243336f8ec71c9d4d57ec17bf795b67f08132a91"},
+ {file = "black-23.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:ad0014efc7acf0bd745792bd0d8857413652979200ab924fbf239062adc12491"},
+ {file = "black-23.7.0-py3-none-any.whl", hash = "sha256:9fd59d418c60c0348505f2ddf9609c1e1de8e7493eab96198fc89d9f865e7a96"},
+ {file = "black-23.7.0.tar.gz", hash = "sha256:022a582720b0d9480ed82576c920a8c1dde97cc38ff11d8d8859b3bd6ca9eedb"},
]
[package.dependencies]
@@ -52,34 +101,405 @@ uvloop = ["uvloop (>=0.15.2)"]
[[package]]
name = "boto3"
-version = "1.26.110"
+version = "1.28.2"
description = "The AWS SDK for Python"
-category = "main"
optional = false
python-versions = ">= 3.7"
files = [
- {file = "boto3-1.26.110-py3-none-any.whl", hash = "sha256:8972a5e0a04ea6f477c41e390765a46ec7bcffb62f99d4a0774ce70fb87bea59"},
- {file = "boto3-1.26.110.tar.gz", hash = "sha256:97d942d958cac28687187b89ee88ac760e0fa3007094cb1d6b16e241144306f3"},
+ {file = "boto3-1.28.2-py3-none-any.whl", hash = "sha256:9933e40dc9ac72deac45cecce2df020e3bf8d0d537538d2b361c17d1cee807cc"},
+ {file = "boto3-1.28.2.tar.gz", hash = "sha256:0d53fe604dc30edded21906bc56b30a7684f0715f4f6897307d53f8184997368"},
]
[package.dependencies]
-botocore = ">=1.29.110,<1.30.0"
+botocore = ">=1.31.2,<1.32.0"
jmespath = ">=0.7.1,<2.0.0"
s3transfer = ">=0.6.0,<0.7.0"
[package.extras]
crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
+[[package]]
+name = "boto3-stubs-lite"
+version = "1.28.2"
+description = "Type annotations for boto3 1.28.2 generated with mypy-boto3-builder 7.14.5"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "boto3-stubs-lite-1.28.2.tar.gz", hash = "sha256:475b6700848a81bda2ca40ad8adfe5bdd227032b82910a27d74576bbb0a94dcc"},
+ {file = "boto3_stubs_lite-1.28.2-py3-none-any.whl", hash = "sha256:fecff74f745887d0e3e1d95ad2aa147bf161a0725c89fbd75c72bfc752b9ac8e"},
+]
+
+[package.dependencies]
+botocore-stubs = "*"
+mypy-boto3-cloudformation = {version = ">=1.28.0,<1.29.0", optional = true, markers = "extra == \"cloudformation\""}
+mypy-boto3-lambda = {version = ">=1.28.0,<1.29.0", optional = true, markers = "extra == \"lambda\""}
+types-s3transfer = "*"
+typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""}
+
+[package.extras]
+accessanalyzer = ["mypy-boto3-accessanalyzer (>=1.28.0,<1.29.0)"]
+account = ["mypy-boto3-account (>=1.28.0,<1.29.0)"]
+acm = ["mypy-boto3-acm (>=1.28.0,<1.29.0)"]
+acm-pca = ["mypy-boto3-acm-pca (>=1.28.0,<1.29.0)"]
+alexaforbusiness = ["mypy-boto3-alexaforbusiness (>=1.28.0,<1.29.0)"]
+all = ["mypy-boto3-accessanalyzer (>=1.28.0,<1.29.0)", "mypy-boto3-account (>=1.28.0,<1.29.0)", "mypy-boto3-acm (>=1.28.0,<1.29.0)", "mypy-boto3-acm-pca (>=1.28.0,<1.29.0)", "mypy-boto3-alexaforbusiness (>=1.28.0,<1.29.0)", "mypy-boto3-amp (>=1.28.0,<1.29.0)", "mypy-boto3-amplify (>=1.28.0,<1.29.0)", "mypy-boto3-amplifybackend (>=1.28.0,<1.29.0)", "mypy-boto3-amplifyuibuilder (>=1.28.0,<1.29.0)", "mypy-boto3-apigateway (>=1.28.0,<1.29.0)", "mypy-boto3-apigatewaymanagementapi (>=1.28.0,<1.29.0)", "mypy-boto3-apigatewayv2 (>=1.28.0,<1.29.0)", "mypy-boto3-appconfig (>=1.28.0,<1.29.0)", "mypy-boto3-appconfigdata (>=1.28.0,<1.29.0)", "mypy-boto3-appfabric (>=1.28.0,<1.29.0)", "mypy-boto3-appflow (>=1.28.0,<1.29.0)", "mypy-boto3-appintegrations (>=1.28.0,<1.29.0)", "mypy-boto3-application-autoscaling (>=1.28.0,<1.29.0)", "mypy-boto3-application-insights (>=1.28.0,<1.29.0)", "mypy-boto3-applicationcostprofiler (>=1.28.0,<1.29.0)", "mypy-boto3-appmesh (>=1.28.0,<1.29.0)", "mypy-boto3-apprunner (>=1.28.0,<1.29.0)", "mypy-boto3-appstream (>=1.28.0,<1.29.0)", "mypy-boto3-appsync (>=1.28.0,<1.29.0)", "mypy-boto3-arc-zonal-shift (>=1.28.0,<1.29.0)", "mypy-boto3-athena (>=1.28.0,<1.29.0)", "mypy-boto3-auditmanager (>=1.28.0,<1.29.0)", "mypy-boto3-autoscaling (>=1.28.0,<1.29.0)", "mypy-boto3-autoscaling-plans (>=1.28.0,<1.29.0)", "mypy-boto3-backup (>=1.28.0,<1.29.0)", "mypy-boto3-backup-gateway (>=1.28.0,<1.29.0)", "mypy-boto3-backupstorage (>=1.28.0,<1.29.0)", "mypy-boto3-batch (>=1.28.0,<1.29.0)", "mypy-boto3-billingconductor (>=1.28.0,<1.29.0)", "mypy-boto3-braket (>=1.28.0,<1.29.0)", "mypy-boto3-budgets (>=1.28.0,<1.29.0)", "mypy-boto3-ce (>=1.28.0,<1.29.0)", "mypy-boto3-chime (>=1.28.0,<1.29.0)", "mypy-boto3-chime-sdk-identity (>=1.28.0,<1.29.0)", "mypy-boto3-chime-sdk-media-pipelines (>=1.28.0,<1.29.0)", "mypy-boto3-chime-sdk-meetings (>=1.28.0,<1.29.0)", "mypy-boto3-chime-sdk-messaging (>=1.28.0,<1.29.0)", "mypy-boto3-chime-sdk-voice (>=1.28.0,<1.29.0)", "mypy-boto3-cleanrooms (>=1.28.0,<1.29.0)", "mypy-boto3-cloud9 (>=1.28.0,<1.29.0)", "mypy-boto3-cloudcontrol (>=1.28.0,<1.29.0)", "mypy-boto3-clouddirectory (>=1.28.0,<1.29.0)", "mypy-boto3-cloudformation (>=1.28.0,<1.29.0)", "mypy-boto3-cloudfront (>=1.28.0,<1.29.0)", "mypy-boto3-cloudhsm (>=1.28.0,<1.29.0)", "mypy-boto3-cloudhsmv2 (>=1.28.0,<1.29.0)", "mypy-boto3-cloudsearch (>=1.28.0,<1.29.0)", "mypy-boto3-cloudsearchdomain (>=1.28.0,<1.29.0)", "mypy-boto3-cloudtrail (>=1.28.0,<1.29.0)", "mypy-boto3-cloudtrail-data (>=1.28.0,<1.29.0)", "mypy-boto3-cloudwatch (>=1.28.0,<1.29.0)", "mypy-boto3-codeartifact (>=1.28.0,<1.29.0)", "mypy-boto3-codebuild (>=1.28.0,<1.29.0)", "mypy-boto3-codecatalyst (>=1.28.0,<1.29.0)", "mypy-boto3-codecommit (>=1.28.0,<1.29.0)", "mypy-boto3-codedeploy (>=1.28.0,<1.29.0)", "mypy-boto3-codeguru-reviewer (>=1.28.0,<1.29.0)", "mypy-boto3-codeguru-security (>=1.28.0,<1.29.0)", "mypy-boto3-codeguruprofiler (>=1.28.0,<1.29.0)", "mypy-boto3-codepipeline (>=1.28.0,<1.29.0)", "mypy-boto3-codestar (>=1.28.0,<1.29.0)", "mypy-boto3-codestar-connections (>=1.28.0,<1.29.0)", "mypy-boto3-codestar-notifications (>=1.28.0,<1.29.0)", "mypy-boto3-cognito-identity (>=1.28.0,<1.29.0)", "mypy-boto3-cognito-idp (>=1.28.0,<1.29.0)", "mypy-boto3-cognito-sync (>=1.28.0,<1.29.0)", "mypy-boto3-comprehend (>=1.28.0,<1.29.0)", "mypy-boto3-comprehendmedical (>=1.28.0,<1.29.0)", "mypy-boto3-compute-optimizer (>=1.28.0,<1.29.0)", "mypy-boto3-config (>=1.28.0,<1.29.0)", "mypy-boto3-connect (>=1.28.0,<1.29.0)", "mypy-boto3-connect-contact-lens (>=1.28.0,<1.29.0)", "mypy-boto3-connectcampaigns (>=1.28.0,<1.29.0)", "mypy-boto3-connectcases (>=1.28.0,<1.29.0)", "mypy-boto3-connectparticipant (>=1.28.0,<1.29.0)", "mypy-boto3-controltower (>=1.28.0,<1.29.0)", "mypy-boto3-cur (>=1.28.0,<1.29.0)", "mypy-boto3-customer-profiles (>=1.28.0,<1.29.0)", "mypy-boto3-databrew (>=1.28.0,<1.29.0)", "mypy-boto3-dataexchange (>=1.28.0,<1.29.0)", "mypy-boto3-datapipeline (>=1.28.0,<1.29.0)", "mypy-boto3-datasync (>=1.28.0,<1.29.0)", "mypy-boto3-dax (>=1.28.0,<1.29.0)", "mypy-boto3-detective (>=1.28.0,<1.29.0)", "mypy-boto3-devicefarm (>=1.28.0,<1.29.0)", "mypy-boto3-devops-guru (>=1.28.0,<1.29.0)", "mypy-boto3-directconnect (>=1.28.0,<1.29.0)", "mypy-boto3-discovery (>=1.28.0,<1.29.0)", "mypy-boto3-dlm (>=1.28.0,<1.29.0)", "mypy-boto3-dms (>=1.28.0,<1.29.0)", "mypy-boto3-docdb (>=1.28.0,<1.29.0)", "mypy-boto3-docdb-elastic (>=1.28.0,<1.29.0)", "mypy-boto3-drs (>=1.28.0,<1.29.0)", "mypy-boto3-ds (>=1.28.0,<1.29.0)", "mypy-boto3-dynamodb (>=1.28.0,<1.29.0)", "mypy-boto3-dynamodbstreams (>=1.28.0,<1.29.0)", "mypy-boto3-ebs (>=1.28.0,<1.29.0)", "mypy-boto3-ec2 (>=1.28.0,<1.29.0)", "mypy-boto3-ec2-instance-connect (>=1.28.0,<1.29.0)", "mypy-boto3-ecr (>=1.28.0,<1.29.0)", "mypy-boto3-ecr-public (>=1.28.0,<1.29.0)", "mypy-boto3-ecs (>=1.28.0,<1.29.0)", "mypy-boto3-efs (>=1.28.0,<1.29.0)", "mypy-boto3-eks (>=1.28.0,<1.29.0)", "mypy-boto3-elastic-inference (>=1.28.0,<1.29.0)", "mypy-boto3-elasticache (>=1.28.0,<1.29.0)", "mypy-boto3-elasticbeanstalk (>=1.28.0,<1.29.0)", "mypy-boto3-elastictranscoder (>=1.28.0,<1.29.0)", "mypy-boto3-elb (>=1.28.0,<1.29.0)", "mypy-boto3-elbv2 (>=1.28.0,<1.29.0)", "mypy-boto3-emr (>=1.28.0,<1.29.0)", "mypy-boto3-emr-containers (>=1.28.0,<1.29.0)", "mypy-boto3-emr-serverless (>=1.28.0,<1.29.0)", "mypy-boto3-es (>=1.28.0,<1.29.0)", "mypy-boto3-events (>=1.28.0,<1.29.0)", "mypy-boto3-evidently (>=1.28.0,<1.29.0)", "mypy-boto3-finspace (>=1.28.0,<1.29.0)", "mypy-boto3-finspace-data (>=1.28.0,<1.29.0)", "mypy-boto3-firehose (>=1.28.0,<1.29.0)", "mypy-boto3-fis (>=1.28.0,<1.29.0)", "mypy-boto3-fms (>=1.28.0,<1.29.0)", "mypy-boto3-forecast (>=1.28.0,<1.29.0)", "mypy-boto3-forecastquery (>=1.28.0,<1.29.0)", "mypy-boto3-frauddetector (>=1.28.0,<1.29.0)", "mypy-boto3-fsx (>=1.28.0,<1.29.0)", "mypy-boto3-gamelift (>=1.28.0,<1.29.0)", "mypy-boto3-gamesparks (>=1.28.0,<1.29.0)", "mypy-boto3-glacier (>=1.28.0,<1.29.0)", "mypy-boto3-globalaccelerator (>=1.28.0,<1.29.0)", "mypy-boto3-glue (>=1.28.0,<1.29.0)", "mypy-boto3-grafana (>=1.28.0,<1.29.0)", "mypy-boto3-greengrass (>=1.28.0,<1.29.0)", "mypy-boto3-greengrassv2 (>=1.28.0,<1.29.0)", "mypy-boto3-groundstation (>=1.28.0,<1.29.0)", "mypy-boto3-guardduty (>=1.28.0,<1.29.0)", "mypy-boto3-health (>=1.28.0,<1.29.0)", "mypy-boto3-healthlake (>=1.28.0,<1.29.0)", "mypy-boto3-honeycode (>=1.28.0,<1.29.0)", "mypy-boto3-iam (>=1.28.0,<1.29.0)", "mypy-boto3-identitystore (>=1.28.0,<1.29.0)", "mypy-boto3-imagebuilder (>=1.28.0,<1.29.0)", "mypy-boto3-importexport (>=1.28.0,<1.29.0)", "mypy-boto3-inspector (>=1.28.0,<1.29.0)", "mypy-boto3-inspector2 (>=1.28.0,<1.29.0)", "mypy-boto3-internetmonitor (>=1.28.0,<1.29.0)", "mypy-boto3-iot (>=1.28.0,<1.29.0)", "mypy-boto3-iot-data (>=1.28.0,<1.29.0)", "mypy-boto3-iot-jobs-data (>=1.28.0,<1.29.0)", "mypy-boto3-iot-roborunner (>=1.28.0,<1.29.0)", "mypy-boto3-iot1click-devices (>=1.28.0,<1.29.0)", "mypy-boto3-iot1click-projects (>=1.28.0,<1.29.0)", "mypy-boto3-iotanalytics (>=1.28.0,<1.29.0)", "mypy-boto3-iotdeviceadvisor (>=1.28.0,<1.29.0)", "mypy-boto3-iotevents (>=1.28.0,<1.29.0)", "mypy-boto3-iotevents-data (>=1.28.0,<1.29.0)", "mypy-boto3-iotfleethub (>=1.28.0,<1.29.0)", "mypy-boto3-iotfleetwise (>=1.28.0,<1.29.0)", "mypy-boto3-iotsecuretunneling (>=1.28.0,<1.29.0)", "mypy-boto3-iotsitewise (>=1.28.0,<1.29.0)", "mypy-boto3-iotthingsgraph (>=1.28.0,<1.29.0)", "mypy-boto3-iottwinmaker (>=1.28.0,<1.29.0)", "mypy-boto3-iotwireless (>=1.28.0,<1.29.0)", "mypy-boto3-ivs (>=1.28.0,<1.29.0)", "mypy-boto3-ivs-realtime (>=1.28.0,<1.29.0)", "mypy-boto3-ivschat (>=1.28.0,<1.29.0)", "mypy-boto3-kafka (>=1.28.0,<1.29.0)", "mypy-boto3-kafkaconnect (>=1.28.0,<1.29.0)", "mypy-boto3-kendra (>=1.28.0,<1.29.0)", "mypy-boto3-kendra-ranking (>=1.28.0,<1.29.0)", "mypy-boto3-keyspaces (>=1.28.0,<1.29.0)", "mypy-boto3-kinesis (>=1.28.0,<1.29.0)", "mypy-boto3-kinesis-video-archived-media (>=1.28.0,<1.29.0)", "mypy-boto3-kinesis-video-media (>=1.28.0,<1.29.0)", "mypy-boto3-kinesis-video-signaling (>=1.28.0,<1.29.0)", "mypy-boto3-kinesis-video-webrtc-storage (>=1.28.0,<1.29.0)", "mypy-boto3-kinesisanalytics (>=1.28.0,<1.29.0)", "mypy-boto3-kinesisanalyticsv2 (>=1.28.0,<1.29.0)", "mypy-boto3-kinesisvideo (>=1.28.0,<1.29.0)", "mypy-boto3-kms (>=1.28.0,<1.29.0)", "mypy-boto3-lakeformation (>=1.28.0,<1.29.0)", "mypy-boto3-lambda (>=1.28.0,<1.29.0)", "mypy-boto3-lex-models (>=1.28.0,<1.29.0)", "mypy-boto3-lex-runtime (>=1.28.0,<1.29.0)", "mypy-boto3-lexv2-models (>=1.28.0,<1.29.0)", "mypy-boto3-lexv2-runtime (>=1.28.0,<1.29.0)", "mypy-boto3-license-manager (>=1.28.0,<1.29.0)", "mypy-boto3-license-manager-linux-subscriptions (>=1.28.0,<1.29.0)", "mypy-boto3-license-manager-user-subscriptions (>=1.28.0,<1.29.0)", "mypy-boto3-lightsail (>=1.28.0,<1.29.0)", "mypy-boto3-location (>=1.28.0,<1.29.0)", "mypy-boto3-logs (>=1.28.0,<1.29.0)", "mypy-boto3-lookoutequipment (>=1.28.0,<1.29.0)", "mypy-boto3-lookoutmetrics (>=1.28.0,<1.29.0)", "mypy-boto3-lookoutvision (>=1.28.0,<1.29.0)", "mypy-boto3-m2 (>=1.28.0,<1.29.0)", "mypy-boto3-machinelearning (>=1.28.0,<1.29.0)", "mypy-boto3-macie (>=1.28.0,<1.29.0)", "mypy-boto3-macie2 (>=1.28.0,<1.29.0)", "mypy-boto3-managedblockchain (>=1.28.0,<1.29.0)", "mypy-boto3-marketplace-catalog (>=1.28.0,<1.29.0)", "mypy-boto3-marketplace-entitlement (>=1.28.0,<1.29.0)", "mypy-boto3-marketplacecommerceanalytics (>=1.28.0,<1.29.0)", "mypy-boto3-mediaconnect (>=1.28.0,<1.29.0)", "mypy-boto3-mediaconvert (>=1.28.0,<1.29.0)", "mypy-boto3-medialive (>=1.28.0,<1.29.0)", "mypy-boto3-mediapackage (>=1.28.0,<1.29.0)", "mypy-boto3-mediapackage-vod (>=1.28.0,<1.29.0)", "mypy-boto3-mediapackagev2 (>=1.28.0,<1.29.0)", "mypy-boto3-mediastore (>=1.28.0,<1.29.0)", "mypy-boto3-mediastore-data (>=1.28.0,<1.29.0)", "mypy-boto3-mediatailor (>=1.28.0,<1.29.0)", "mypy-boto3-memorydb (>=1.28.0,<1.29.0)", "mypy-boto3-meteringmarketplace (>=1.28.0,<1.29.0)", "mypy-boto3-mgh (>=1.28.0,<1.29.0)", "mypy-boto3-mgn (>=1.28.0,<1.29.0)", "mypy-boto3-migration-hub-refactor-spaces (>=1.28.0,<1.29.0)", "mypy-boto3-migrationhub-config (>=1.28.0,<1.29.0)", "mypy-boto3-migrationhuborchestrator (>=1.28.0,<1.29.0)", "mypy-boto3-migrationhubstrategy (>=1.28.0,<1.29.0)", "mypy-boto3-mobile (>=1.28.0,<1.29.0)", "mypy-boto3-mq (>=1.28.0,<1.29.0)", "mypy-boto3-mturk (>=1.28.0,<1.29.0)", "mypy-boto3-mwaa (>=1.28.0,<1.29.0)", "mypy-boto3-neptune (>=1.28.0,<1.29.0)", "mypy-boto3-network-firewall (>=1.28.0,<1.29.0)", "mypy-boto3-networkmanager (>=1.28.0,<1.29.0)", "mypy-boto3-nimble (>=1.28.0,<1.29.0)", "mypy-boto3-oam (>=1.28.0,<1.29.0)", "mypy-boto3-omics (>=1.28.0,<1.29.0)", "mypy-boto3-opensearch (>=1.28.0,<1.29.0)", "mypy-boto3-opensearchserverless (>=1.28.0,<1.29.0)", "mypy-boto3-opsworks (>=1.28.0,<1.29.0)", "mypy-boto3-opsworkscm (>=1.28.0,<1.29.0)", "mypy-boto3-organizations (>=1.28.0,<1.29.0)", "mypy-boto3-osis (>=1.28.0,<1.29.0)", "mypy-boto3-outposts (>=1.28.0,<1.29.0)", "mypy-boto3-panorama (>=1.28.0,<1.29.0)", "mypy-boto3-payment-cryptography (>=1.28.0,<1.29.0)", "mypy-boto3-payment-cryptography-data (>=1.28.0,<1.29.0)", "mypy-boto3-personalize (>=1.28.0,<1.29.0)", "mypy-boto3-personalize-events (>=1.28.0,<1.29.0)", "mypy-boto3-personalize-runtime (>=1.28.0,<1.29.0)", "mypy-boto3-pi (>=1.28.0,<1.29.0)", "mypy-boto3-pinpoint (>=1.28.0,<1.29.0)", "mypy-boto3-pinpoint-email (>=1.28.0,<1.29.0)", "mypy-boto3-pinpoint-sms-voice (>=1.28.0,<1.29.0)", "mypy-boto3-pinpoint-sms-voice-v2 (>=1.28.0,<1.29.0)", "mypy-boto3-pipes (>=1.28.0,<1.29.0)", "mypy-boto3-polly (>=1.28.0,<1.29.0)", "mypy-boto3-pricing (>=1.28.0,<1.29.0)", "mypy-boto3-privatenetworks (>=1.28.0,<1.29.0)", "mypy-boto3-proton (>=1.28.0,<1.29.0)", "mypy-boto3-qldb (>=1.28.0,<1.29.0)", "mypy-boto3-qldb-session (>=1.28.0,<1.29.0)", "mypy-boto3-quicksight (>=1.28.0,<1.29.0)", "mypy-boto3-ram (>=1.28.0,<1.29.0)", "mypy-boto3-rbin (>=1.28.0,<1.29.0)", "mypy-boto3-rds (>=1.28.0,<1.29.0)", "mypy-boto3-rds-data (>=1.28.0,<1.29.0)", "mypy-boto3-redshift (>=1.28.0,<1.29.0)", "mypy-boto3-redshift-data (>=1.28.0,<1.29.0)", "mypy-boto3-redshift-serverless (>=1.28.0,<1.29.0)", "mypy-boto3-rekognition (>=1.28.0,<1.29.0)", "mypy-boto3-resiliencehub (>=1.28.0,<1.29.0)", "mypy-boto3-resource-explorer-2 (>=1.28.0,<1.29.0)", "mypy-boto3-resource-groups (>=1.28.0,<1.29.0)", "mypy-boto3-resourcegroupstaggingapi (>=1.28.0,<1.29.0)", "mypy-boto3-robomaker (>=1.28.0,<1.29.0)", "mypy-boto3-rolesanywhere (>=1.28.0,<1.29.0)", "mypy-boto3-route53 (>=1.28.0,<1.29.0)", "mypy-boto3-route53-recovery-cluster (>=1.28.0,<1.29.0)", "mypy-boto3-route53-recovery-control-config (>=1.28.0,<1.29.0)", "mypy-boto3-route53-recovery-readiness (>=1.28.0,<1.29.0)", "mypy-boto3-route53domains (>=1.28.0,<1.29.0)", "mypy-boto3-route53resolver (>=1.28.0,<1.29.0)", "mypy-boto3-rum (>=1.28.0,<1.29.0)", "mypy-boto3-s3 (>=1.28.0,<1.29.0)", "mypy-boto3-s3control (>=1.28.0,<1.29.0)", "mypy-boto3-s3outposts (>=1.28.0,<1.29.0)", "mypy-boto3-sagemaker (>=1.28.0,<1.29.0)", "mypy-boto3-sagemaker-a2i-runtime (>=1.28.0,<1.29.0)", "mypy-boto3-sagemaker-edge (>=1.28.0,<1.29.0)", "mypy-boto3-sagemaker-featurestore-runtime (>=1.28.0,<1.29.0)", "mypy-boto3-sagemaker-geospatial (>=1.28.0,<1.29.0)", "mypy-boto3-sagemaker-metrics (>=1.28.0,<1.29.0)", "mypy-boto3-sagemaker-runtime (>=1.28.0,<1.29.0)", "mypy-boto3-savingsplans (>=1.28.0,<1.29.0)", "mypy-boto3-scheduler (>=1.28.0,<1.29.0)", "mypy-boto3-schemas (>=1.28.0,<1.29.0)", "mypy-boto3-sdb (>=1.28.0,<1.29.0)", "mypy-boto3-secretsmanager (>=1.28.0,<1.29.0)", "mypy-boto3-securityhub (>=1.28.0,<1.29.0)", "mypy-boto3-securitylake (>=1.28.0,<1.29.0)", "mypy-boto3-serverlessrepo (>=1.28.0,<1.29.0)", "mypy-boto3-service-quotas (>=1.28.0,<1.29.0)", "mypy-boto3-servicecatalog (>=1.28.0,<1.29.0)", "mypy-boto3-servicecatalog-appregistry (>=1.28.0,<1.29.0)", "mypy-boto3-servicediscovery (>=1.28.0,<1.29.0)", "mypy-boto3-ses (>=1.28.0,<1.29.0)", "mypy-boto3-sesv2 (>=1.28.0,<1.29.0)", "mypy-boto3-shield (>=1.28.0,<1.29.0)", "mypy-boto3-signer (>=1.28.0,<1.29.0)", "mypy-boto3-simspaceweaver (>=1.28.0,<1.29.0)", "mypy-boto3-sms (>=1.28.0,<1.29.0)", "mypy-boto3-sms-voice (>=1.28.0,<1.29.0)", "mypy-boto3-snow-device-management (>=1.28.0,<1.29.0)", "mypy-boto3-snowball (>=1.28.0,<1.29.0)", "mypy-boto3-sns (>=1.28.0,<1.29.0)", "mypy-boto3-sqs (>=1.28.0,<1.29.0)", "mypy-boto3-ssm (>=1.28.0,<1.29.0)", "mypy-boto3-ssm-contacts (>=1.28.0,<1.29.0)", "mypy-boto3-ssm-incidents (>=1.28.0,<1.29.0)", "mypy-boto3-ssm-sap (>=1.28.0,<1.29.0)", "mypy-boto3-sso (>=1.28.0,<1.29.0)", "mypy-boto3-sso-admin (>=1.28.0,<1.29.0)", "mypy-boto3-sso-oidc (>=1.28.0,<1.29.0)", "mypy-boto3-stepfunctions (>=1.28.0,<1.29.0)", "mypy-boto3-storagegateway (>=1.28.0,<1.29.0)", "mypy-boto3-sts (>=1.28.0,<1.29.0)", "mypy-boto3-support (>=1.28.0,<1.29.0)", "mypy-boto3-support-app (>=1.28.0,<1.29.0)", "mypy-boto3-swf (>=1.28.0,<1.29.0)", "mypy-boto3-synthetics (>=1.28.0,<1.29.0)", "mypy-boto3-textract (>=1.28.0,<1.29.0)", "mypy-boto3-timestream-query (>=1.28.0,<1.29.0)", "mypy-boto3-timestream-write (>=1.28.0,<1.29.0)", "mypy-boto3-tnb (>=1.28.0,<1.29.0)", "mypy-boto3-transcribe (>=1.28.0,<1.29.0)", "mypy-boto3-transfer (>=1.28.0,<1.29.0)", "mypy-boto3-translate (>=1.28.0,<1.29.0)", "mypy-boto3-verifiedpermissions (>=1.28.0,<1.29.0)", "mypy-boto3-voice-id (>=1.28.0,<1.29.0)", "mypy-boto3-vpc-lattice (>=1.28.0,<1.29.0)", "mypy-boto3-waf (>=1.28.0,<1.29.0)", "mypy-boto3-waf-regional (>=1.28.0,<1.29.0)", "mypy-boto3-wafv2 (>=1.28.0,<1.29.0)", "mypy-boto3-wellarchitected (>=1.28.0,<1.29.0)", "mypy-boto3-wisdom (>=1.28.0,<1.29.0)", "mypy-boto3-workdocs (>=1.28.0,<1.29.0)", "mypy-boto3-worklink (>=1.28.0,<1.29.0)", "mypy-boto3-workmail (>=1.28.0,<1.29.0)", "mypy-boto3-workmailmessageflow (>=1.28.0,<1.29.0)", "mypy-boto3-workspaces (>=1.28.0,<1.29.0)", "mypy-boto3-workspaces-web (>=1.28.0,<1.29.0)", "mypy-boto3-xray (>=1.28.0,<1.29.0)"]
+amp = ["mypy-boto3-amp (>=1.28.0,<1.29.0)"]
+amplify = ["mypy-boto3-amplify (>=1.28.0,<1.29.0)"]
+amplifybackend = ["mypy-boto3-amplifybackend (>=1.28.0,<1.29.0)"]
+amplifyuibuilder = ["mypy-boto3-amplifyuibuilder (>=1.28.0,<1.29.0)"]
+apigateway = ["mypy-boto3-apigateway (>=1.28.0,<1.29.0)"]
+apigatewaymanagementapi = ["mypy-boto3-apigatewaymanagementapi (>=1.28.0,<1.29.0)"]
+apigatewayv2 = ["mypy-boto3-apigatewayv2 (>=1.28.0,<1.29.0)"]
+appconfig = ["mypy-boto3-appconfig (>=1.28.0,<1.29.0)"]
+appconfigdata = ["mypy-boto3-appconfigdata (>=1.28.0,<1.29.0)"]
+appfabric = ["mypy-boto3-appfabric (>=1.28.0,<1.29.0)"]
+appflow = ["mypy-boto3-appflow (>=1.28.0,<1.29.0)"]
+appintegrations = ["mypy-boto3-appintegrations (>=1.28.0,<1.29.0)"]
+application-autoscaling = ["mypy-boto3-application-autoscaling (>=1.28.0,<1.29.0)"]
+application-insights = ["mypy-boto3-application-insights (>=1.28.0,<1.29.0)"]
+applicationcostprofiler = ["mypy-boto3-applicationcostprofiler (>=1.28.0,<1.29.0)"]
+appmesh = ["mypy-boto3-appmesh (>=1.28.0,<1.29.0)"]
+apprunner = ["mypy-boto3-apprunner (>=1.28.0,<1.29.0)"]
+appstream = ["mypy-boto3-appstream (>=1.28.0,<1.29.0)"]
+appsync = ["mypy-boto3-appsync (>=1.28.0,<1.29.0)"]
+arc-zonal-shift = ["mypy-boto3-arc-zonal-shift (>=1.28.0,<1.29.0)"]
+athena = ["mypy-boto3-athena (>=1.28.0,<1.29.0)"]
+auditmanager = ["mypy-boto3-auditmanager (>=1.28.0,<1.29.0)"]
+autoscaling = ["mypy-boto3-autoscaling (>=1.28.0,<1.29.0)"]
+autoscaling-plans = ["mypy-boto3-autoscaling-plans (>=1.28.0,<1.29.0)"]
+backup = ["mypy-boto3-backup (>=1.28.0,<1.29.0)"]
+backup-gateway = ["mypy-boto3-backup-gateway (>=1.28.0,<1.29.0)"]
+backupstorage = ["mypy-boto3-backupstorage (>=1.28.0,<1.29.0)"]
+batch = ["mypy-boto3-batch (>=1.28.0,<1.29.0)"]
+billingconductor = ["mypy-boto3-billingconductor (>=1.28.0,<1.29.0)"]
+boto3 = ["boto3 (==1.28.2)", "botocore (==1.31.2)"]
+braket = ["mypy-boto3-braket (>=1.28.0,<1.29.0)"]
+budgets = ["mypy-boto3-budgets (>=1.28.0,<1.29.0)"]
+ce = ["mypy-boto3-ce (>=1.28.0,<1.29.0)"]
+chime = ["mypy-boto3-chime (>=1.28.0,<1.29.0)"]
+chime-sdk-identity = ["mypy-boto3-chime-sdk-identity (>=1.28.0,<1.29.0)"]
+chime-sdk-media-pipelines = ["mypy-boto3-chime-sdk-media-pipelines (>=1.28.0,<1.29.0)"]
+chime-sdk-meetings = ["mypy-boto3-chime-sdk-meetings (>=1.28.0,<1.29.0)"]
+chime-sdk-messaging = ["mypy-boto3-chime-sdk-messaging (>=1.28.0,<1.29.0)"]
+chime-sdk-voice = ["mypy-boto3-chime-sdk-voice (>=1.28.0,<1.29.0)"]
+cleanrooms = ["mypy-boto3-cleanrooms (>=1.28.0,<1.29.0)"]
+cloud9 = ["mypy-boto3-cloud9 (>=1.28.0,<1.29.0)"]
+cloudcontrol = ["mypy-boto3-cloudcontrol (>=1.28.0,<1.29.0)"]
+clouddirectory = ["mypy-boto3-clouddirectory (>=1.28.0,<1.29.0)"]
+cloudformation = ["mypy-boto3-cloudformation (>=1.28.0,<1.29.0)"]
+cloudfront = ["mypy-boto3-cloudfront (>=1.28.0,<1.29.0)"]
+cloudhsm = ["mypy-boto3-cloudhsm (>=1.28.0,<1.29.0)"]
+cloudhsmv2 = ["mypy-boto3-cloudhsmv2 (>=1.28.0,<1.29.0)"]
+cloudsearch = ["mypy-boto3-cloudsearch (>=1.28.0,<1.29.0)"]
+cloudsearchdomain = ["mypy-boto3-cloudsearchdomain (>=1.28.0,<1.29.0)"]
+cloudtrail = ["mypy-boto3-cloudtrail (>=1.28.0,<1.29.0)"]
+cloudtrail-data = ["mypy-boto3-cloudtrail-data (>=1.28.0,<1.29.0)"]
+cloudwatch = ["mypy-boto3-cloudwatch (>=1.28.0,<1.29.0)"]
+codeartifact = ["mypy-boto3-codeartifact (>=1.28.0,<1.29.0)"]
+codebuild = ["mypy-boto3-codebuild (>=1.28.0,<1.29.0)"]
+codecatalyst = ["mypy-boto3-codecatalyst (>=1.28.0,<1.29.0)"]
+codecommit = ["mypy-boto3-codecommit (>=1.28.0,<1.29.0)"]
+codedeploy = ["mypy-boto3-codedeploy (>=1.28.0,<1.29.0)"]
+codeguru-reviewer = ["mypy-boto3-codeguru-reviewer (>=1.28.0,<1.29.0)"]
+codeguru-security = ["mypy-boto3-codeguru-security (>=1.28.0,<1.29.0)"]
+codeguruprofiler = ["mypy-boto3-codeguruprofiler (>=1.28.0,<1.29.0)"]
+codepipeline = ["mypy-boto3-codepipeline (>=1.28.0,<1.29.0)"]
+codestar = ["mypy-boto3-codestar (>=1.28.0,<1.29.0)"]
+codestar-connections = ["mypy-boto3-codestar-connections (>=1.28.0,<1.29.0)"]
+codestar-notifications = ["mypy-boto3-codestar-notifications (>=1.28.0,<1.29.0)"]
+cognito-identity = ["mypy-boto3-cognito-identity (>=1.28.0,<1.29.0)"]
+cognito-idp = ["mypy-boto3-cognito-idp (>=1.28.0,<1.29.0)"]
+cognito-sync = ["mypy-boto3-cognito-sync (>=1.28.0,<1.29.0)"]
+comprehend = ["mypy-boto3-comprehend (>=1.28.0,<1.29.0)"]
+comprehendmedical = ["mypy-boto3-comprehendmedical (>=1.28.0,<1.29.0)"]
+compute-optimizer = ["mypy-boto3-compute-optimizer (>=1.28.0,<1.29.0)"]
+config = ["mypy-boto3-config (>=1.28.0,<1.29.0)"]
+connect = ["mypy-boto3-connect (>=1.28.0,<1.29.0)"]
+connect-contact-lens = ["mypy-boto3-connect-contact-lens (>=1.28.0,<1.29.0)"]
+connectcampaigns = ["mypy-boto3-connectcampaigns (>=1.28.0,<1.29.0)"]
+connectcases = ["mypy-boto3-connectcases (>=1.28.0,<1.29.0)"]
+connectparticipant = ["mypy-boto3-connectparticipant (>=1.28.0,<1.29.0)"]
+controltower = ["mypy-boto3-controltower (>=1.28.0,<1.29.0)"]
+cur = ["mypy-boto3-cur (>=1.28.0,<1.29.0)"]
+customer-profiles = ["mypy-boto3-customer-profiles (>=1.28.0,<1.29.0)"]
+databrew = ["mypy-boto3-databrew (>=1.28.0,<1.29.0)"]
+dataexchange = ["mypy-boto3-dataexchange (>=1.28.0,<1.29.0)"]
+datapipeline = ["mypy-boto3-datapipeline (>=1.28.0,<1.29.0)"]
+datasync = ["mypy-boto3-datasync (>=1.28.0,<1.29.0)"]
+dax = ["mypy-boto3-dax (>=1.28.0,<1.29.0)"]
+detective = ["mypy-boto3-detective (>=1.28.0,<1.29.0)"]
+devicefarm = ["mypy-boto3-devicefarm (>=1.28.0,<1.29.0)"]
+devops-guru = ["mypy-boto3-devops-guru (>=1.28.0,<1.29.0)"]
+directconnect = ["mypy-boto3-directconnect (>=1.28.0,<1.29.0)"]
+discovery = ["mypy-boto3-discovery (>=1.28.0,<1.29.0)"]
+dlm = ["mypy-boto3-dlm (>=1.28.0,<1.29.0)"]
+dms = ["mypy-boto3-dms (>=1.28.0,<1.29.0)"]
+docdb = ["mypy-boto3-docdb (>=1.28.0,<1.29.0)"]
+docdb-elastic = ["mypy-boto3-docdb-elastic (>=1.28.0,<1.29.0)"]
+drs = ["mypy-boto3-drs (>=1.28.0,<1.29.0)"]
+ds = ["mypy-boto3-ds (>=1.28.0,<1.29.0)"]
+dynamodb = ["mypy-boto3-dynamodb (>=1.28.0,<1.29.0)"]
+dynamodbstreams = ["mypy-boto3-dynamodbstreams (>=1.28.0,<1.29.0)"]
+ebs = ["mypy-boto3-ebs (>=1.28.0,<1.29.0)"]
+ec2 = ["mypy-boto3-ec2 (>=1.28.0,<1.29.0)"]
+ec2-instance-connect = ["mypy-boto3-ec2-instance-connect (>=1.28.0,<1.29.0)"]
+ecr = ["mypy-boto3-ecr (>=1.28.0,<1.29.0)"]
+ecr-public = ["mypy-boto3-ecr-public (>=1.28.0,<1.29.0)"]
+ecs = ["mypy-boto3-ecs (>=1.28.0,<1.29.0)"]
+efs = ["mypy-boto3-efs (>=1.28.0,<1.29.0)"]
+eks = ["mypy-boto3-eks (>=1.28.0,<1.29.0)"]
+elastic-inference = ["mypy-boto3-elastic-inference (>=1.28.0,<1.29.0)"]
+elasticache = ["mypy-boto3-elasticache (>=1.28.0,<1.29.0)"]
+elasticbeanstalk = ["mypy-boto3-elasticbeanstalk (>=1.28.0,<1.29.0)"]
+elastictranscoder = ["mypy-boto3-elastictranscoder (>=1.28.0,<1.29.0)"]
+elb = ["mypy-boto3-elb (>=1.28.0,<1.29.0)"]
+elbv2 = ["mypy-boto3-elbv2 (>=1.28.0,<1.29.0)"]
+emr = ["mypy-boto3-emr (>=1.28.0,<1.29.0)"]
+emr-containers = ["mypy-boto3-emr-containers (>=1.28.0,<1.29.0)"]
+emr-serverless = ["mypy-boto3-emr-serverless (>=1.28.0,<1.29.0)"]
+es = ["mypy-boto3-es (>=1.28.0,<1.29.0)"]
+essential = ["mypy-boto3-cloudformation (>=1.28.0,<1.29.0)", "mypy-boto3-dynamodb (>=1.28.0,<1.29.0)", "mypy-boto3-ec2 (>=1.28.0,<1.29.0)", "mypy-boto3-lambda (>=1.28.0,<1.29.0)", "mypy-boto3-rds (>=1.28.0,<1.29.0)", "mypy-boto3-s3 (>=1.28.0,<1.29.0)", "mypy-boto3-sqs (>=1.28.0,<1.29.0)"]
+events = ["mypy-boto3-events (>=1.28.0,<1.29.0)"]
+evidently = ["mypy-boto3-evidently (>=1.28.0,<1.29.0)"]
+finspace = ["mypy-boto3-finspace (>=1.28.0,<1.29.0)"]
+finspace-data = ["mypy-boto3-finspace-data (>=1.28.0,<1.29.0)"]
+firehose = ["mypy-boto3-firehose (>=1.28.0,<1.29.0)"]
+fis = ["mypy-boto3-fis (>=1.28.0,<1.29.0)"]
+fms = ["mypy-boto3-fms (>=1.28.0,<1.29.0)"]
+forecast = ["mypy-boto3-forecast (>=1.28.0,<1.29.0)"]
+forecastquery = ["mypy-boto3-forecastquery (>=1.28.0,<1.29.0)"]
+frauddetector = ["mypy-boto3-frauddetector (>=1.28.0,<1.29.0)"]
+fsx = ["mypy-boto3-fsx (>=1.28.0,<1.29.0)"]
+gamelift = ["mypy-boto3-gamelift (>=1.28.0,<1.29.0)"]
+gamesparks = ["mypy-boto3-gamesparks (>=1.28.0,<1.29.0)"]
+glacier = ["mypy-boto3-glacier (>=1.28.0,<1.29.0)"]
+globalaccelerator = ["mypy-boto3-globalaccelerator (>=1.28.0,<1.29.0)"]
+glue = ["mypy-boto3-glue (>=1.28.0,<1.29.0)"]
+grafana = ["mypy-boto3-grafana (>=1.28.0,<1.29.0)"]
+greengrass = ["mypy-boto3-greengrass (>=1.28.0,<1.29.0)"]
+greengrassv2 = ["mypy-boto3-greengrassv2 (>=1.28.0,<1.29.0)"]
+groundstation = ["mypy-boto3-groundstation (>=1.28.0,<1.29.0)"]
+guardduty = ["mypy-boto3-guardduty (>=1.28.0,<1.29.0)"]
+health = ["mypy-boto3-health (>=1.28.0,<1.29.0)"]
+healthlake = ["mypy-boto3-healthlake (>=1.28.0,<1.29.0)"]
+honeycode = ["mypy-boto3-honeycode (>=1.28.0,<1.29.0)"]
+iam = ["mypy-boto3-iam (>=1.28.0,<1.29.0)"]
+identitystore = ["mypy-boto3-identitystore (>=1.28.0,<1.29.0)"]
+imagebuilder = ["mypy-boto3-imagebuilder (>=1.28.0,<1.29.0)"]
+importexport = ["mypy-boto3-importexport (>=1.28.0,<1.29.0)"]
+inspector = ["mypy-boto3-inspector (>=1.28.0,<1.29.0)"]
+inspector2 = ["mypy-boto3-inspector2 (>=1.28.0,<1.29.0)"]
+internetmonitor = ["mypy-boto3-internetmonitor (>=1.28.0,<1.29.0)"]
+iot = ["mypy-boto3-iot (>=1.28.0,<1.29.0)"]
+iot-data = ["mypy-boto3-iot-data (>=1.28.0,<1.29.0)"]
+iot-jobs-data = ["mypy-boto3-iot-jobs-data (>=1.28.0,<1.29.0)"]
+iot-roborunner = ["mypy-boto3-iot-roborunner (>=1.28.0,<1.29.0)"]
+iot1click-devices = ["mypy-boto3-iot1click-devices (>=1.28.0,<1.29.0)"]
+iot1click-projects = ["mypy-boto3-iot1click-projects (>=1.28.0,<1.29.0)"]
+iotanalytics = ["mypy-boto3-iotanalytics (>=1.28.0,<1.29.0)"]
+iotdeviceadvisor = ["mypy-boto3-iotdeviceadvisor (>=1.28.0,<1.29.0)"]
+iotevents = ["mypy-boto3-iotevents (>=1.28.0,<1.29.0)"]
+iotevents-data = ["mypy-boto3-iotevents-data (>=1.28.0,<1.29.0)"]
+iotfleethub = ["mypy-boto3-iotfleethub (>=1.28.0,<1.29.0)"]
+iotfleetwise = ["mypy-boto3-iotfleetwise (>=1.28.0,<1.29.0)"]
+iotsecuretunneling = ["mypy-boto3-iotsecuretunneling (>=1.28.0,<1.29.0)"]
+iotsitewise = ["mypy-boto3-iotsitewise (>=1.28.0,<1.29.0)"]
+iotthingsgraph = ["mypy-boto3-iotthingsgraph (>=1.28.0,<1.29.0)"]
+iottwinmaker = ["mypy-boto3-iottwinmaker (>=1.28.0,<1.29.0)"]
+iotwireless = ["mypy-boto3-iotwireless (>=1.28.0,<1.29.0)"]
+ivs = ["mypy-boto3-ivs (>=1.28.0,<1.29.0)"]
+ivs-realtime = ["mypy-boto3-ivs-realtime (>=1.28.0,<1.29.0)"]
+ivschat = ["mypy-boto3-ivschat (>=1.28.0,<1.29.0)"]
+kafka = ["mypy-boto3-kafka (>=1.28.0,<1.29.0)"]
+kafkaconnect = ["mypy-boto3-kafkaconnect (>=1.28.0,<1.29.0)"]
+kendra = ["mypy-boto3-kendra (>=1.28.0,<1.29.0)"]
+kendra-ranking = ["mypy-boto3-kendra-ranking (>=1.28.0,<1.29.0)"]
+keyspaces = ["mypy-boto3-keyspaces (>=1.28.0,<1.29.0)"]
+kinesis = ["mypy-boto3-kinesis (>=1.28.0,<1.29.0)"]
+kinesis-video-archived-media = ["mypy-boto3-kinesis-video-archived-media (>=1.28.0,<1.29.0)"]
+kinesis-video-media = ["mypy-boto3-kinesis-video-media (>=1.28.0,<1.29.0)"]
+kinesis-video-signaling = ["mypy-boto3-kinesis-video-signaling (>=1.28.0,<1.29.0)"]
+kinesis-video-webrtc-storage = ["mypy-boto3-kinesis-video-webrtc-storage (>=1.28.0,<1.29.0)"]
+kinesisanalytics = ["mypy-boto3-kinesisanalytics (>=1.28.0,<1.29.0)"]
+kinesisanalyticsv2 = ["mypy-boto3-kinesisanalyticsv2 (>=1.28.0,<1.29.0)"]
+kinesisvideo = ["mypy-boto3-kinesisvideo (>=1.28.0,<1.29.0)"]
+kms = ["mypy-boto3-kms (>=1.28.0,<1.29.0)"]
+lakeformation = ["mypy-boto3-lakeformation (>=1.28.0,<1.29.0)"]
+lambda = ["mypy-boto3-lambda (>=1.28.0,<1.29.0)"]
+lex-models = ["mypy-boto3-lex-models (>=1.28.0,<1.29.0)"]
+lex-runtime = ["mypy-boto3-lex-runtime (>=1.28.0,<1.29.0)"]
+lexv2-models = ["mypy-boto3-lexv2-models (>=1.28.0,<1.29.0)"]
+lexv2-runtime = ["mypy-boto3-lexv2-runtime (>=1.28.0,<1.29.0)"]
+license-manager = ["mypy-boto3-license-manager (>=1.28.0,<1.29.0)"]
+license-manager-linux-subscriptions = ["mypy-boto3-license-manager-linux-subscriptions (>=1.28.0,<1.29.0)"]
+license-manager-user-subscriptions = ["mypy-boto3-license-manager-user-subscriptions (>=1.28.0,<1.29.0)"]
+lightsail = ["mypy-boto3-lightsail (>=1.28.0,<1.29.0)"]
+location = ["mypy-boto3-location (>=1.28.0,<1.29.0)"]
+logs = ["mypy-boto3-logs (>=1.28.0,<1.29.0)"]
+lookoutequipment = ["mypy-boto3-lookoutequipment (>=1.28.0,<1.29.0)"]
+lookoutmetrics = ["mypy-boto3-lookoutmetrics (>=1.28.0,<1.29.0)"]
+lookoutvision = ["mypy-boto3-lookoutvision (>=1.28.0,<1.29.0)"]
+m2 = ["mypy-boto3-m2 (>=1.28.0,<1.29.0)"]
+machinelearning = ["mypy-boto3-machinelearning (>=1.28.0,<1.29.0)"]
+macie = ["mypy-boto3-macie (>=1.28.0,<1.29.0)"]
+macie2 = ["mypy-boto3-macie2 (>=1.28.0,<1.29.0)"]
+managedblockchain = ["mypy-boto3-managedblockchain (>=1.28.0,<1.29.0)"]
+marketplace-catalog = ["mypy-boto3-marketplace-catalog (>=1.28.0,<1.29.0)"]
+marketplace-entitlement = ["mypy-boto3-marketplace-entitlement (>=1.28.0,<1.29.0)"]
+marketplacecommerceanalytics = ["mypy-boto3-marketplacecommerceanalytics (>=1.28.0,<1.29.0)"]
+mediaconnect = ["mypy-boto3-mediaconnect (>=1.28.0,<1.29.0)"]
+mediaconvert = ["mypy-boto3-mediaconvert (>=1.28.0,<1.29.0)"]
+medialive = ["mypy-boto3-medialive (>=1.28.0,<1.29.0)"]
+mediapackage = ["mypy-boto3-mediapackage (>=1.28.0,<1.29.0)"]
+mediapackage-vod = ["mypy-boto3-mediapackage-vod (>=1.28.0,<1.29.0)"]
+mediapackagev2 = ["mypy-boto3-mediapackagev2 (>=1.28.0,<1.29.0)"]
+mediastore = ["mypy-boto3-mediastore (>=1.28.0,<1.29.0)"]
+mediastore-data = ["mypy-boto3-mediastore-data (>=1.28.0,<1.29.0)"]
+mediatailor = ["mypy-boto3-mediatailor (>=1.28.0,<1.29.0)"]
+memorydb = ["mypy-boto3-memorydb (>=1.28.0,<1.29.0)"]
+meteringmarketplace = ["mypy-boto3-meteringmarketplace (>=1.28.0,<1.29.0)"]
+mgh = ["mypy-boto3-mgh (>=1.28.0,<1.29.0)"]
+mgn = ["mypy-boto3-mgn (>=1.28.0,<1.29.0)"]
+migration-hub-refactor-spaces = ["mypy-boto3-migration-hub-refactor-spaces (>=1.28.0,<1.29.0)"]
+migrationhub-config = ["mypy-boto3-migrationhub-config (>=1.28.0,<1.29.0)"]
+migrationhuborchestrator = ["mypy-boto3-migrationhuborchestrator (>=1.28.0,<1.29.0)"]
+migrationhubstrategy = ["mypy-boto3-migrationhubstrategy (>=1.28.0,<1.29.0)"]
+mobile = ["mypy-boto3-mobile (>=1.28.0,<1.29.0)"]
+mq = ["mypy-boto3-mq (>=1.28.0,<1.29.0)"]
+mturk = ["mypy-boto3-mturk (>=1.28.0,<1.29.0)"]
+mwaa = ["mypy-boto3-mwaa (>=1.28.0,<1.29.0)"]
+neptune = ["mypy-boto3-neptune (>=1.28.0,<1.29.0)"]
+network-firewall = ["mypy-boto3-network-firewall (>=1.28.0,<1.29.0)"]
+networkmanager = ["mypy-boto3-networkmanager (>=1.28.0,<1.29.0)"]
+nimble = ["mypy-boto3-nimble (>=1.28.0,<1.29.0)"]
+oam = ["mypy-boto3-oam (>=1.28.0,<1.29.0)"]
+omics = ["mypy-boto3-omics (>=1.28.0,<1.29.0)"]
+opensearch = ["mypy-boto3-opensearch (>=1.28.0,<1.29.0)"]
+opensearchserverless = ["mypy-boto3-opensearchserverless (>=1.28.0,<1.29.0)"]
+opsworks = ["mypy-boto3-opsworks (>=1.28.0,<1.29.0)"]
+opsworkscm = ["mypy-boto3-opsworkscm (>=1.28.0,<1.29.0)"]
+organizations = ["mypy-boto3-organizations (>=1.28.0,<1.29.0)"]
+osis = ["mypy-boto3-osis (>=1.28.0,<1.29.0)"]
+outposts = ["mypy-boto3-outposts (>=1.28.0,<1.29.0)"]
+panorama = ["mypy-boto3-panorama (>=1.28.0,<1.29.0)"]
+payment-cryptography = ["mypy-boto3-payment-cryptography (>=1.28.0,<1.29.0)"]
+payment-cryptography-data = ["mypy-boto3-payment-cryptography-data (>=1.28.0,<1.29.0)"]
+personalize = ["mypy-boto3-personalize (>=1.28.0,<1.29.0)"]
+personalize-events = ["mypy-boto3-personalize-events (>=1.28.0,<1.29.0)"]
+personalize-runtime = ["mypy-boto3-personalize-runtime (>=1.28.0,<1.29.0)"]
+pi = ["mypy-boto3-pi (>=1.28.0,<1.29.0)"]
+pinpoint = ["mypy-boto3-pinpoint (>=1.28.0,<1.29.0)"]
+pinpoint-email = ["mypy-boto3-pinpoint-email (>=1.28.0,<1.29.0)"]
+pinpoint-sms-voice = ["mypy-boto3-pinpoint-sms-voice (>=1.28.0,<1.29.0)"]
+pinpoint-sms-voice-v2 = ["mypy-boto3-pinpoint-sms-voice-v2 (>=1.28.0,<1.29.0)"]
+pipes = ["mypy-boto3-pipes (>=1.28.0,<1.29.0)"]
+polly = ["mypy-boto3-polly (>=1.28.0,<1.29.0)"]
+pricing = ["mypy-boto3-pricing (>=1.28.0,<1.29.0)"]
+privatenetworks = ["mypy-boto3-privatenetworks (>=1.28.0,<1.29.0)"]
+proton = ["mypy-boto3-proton (>=1.28.0,<1.29.0)"]
+qldb = ["mypy-boto3-qldb (>=1.28.0,<1.29.0)"]
+qldb-session = ["mypy-boto3-qldb-session (>=1.28.0,<1.29.0)"]
+quicksight = ["mypy-boto3-quicksight (>=1.28.0,<1.29.0)"]
+ram = ["mypy-boto3-ram (>=1.28.0,<1.29.0)"]
+rbin = ["mypy-boto3-rbin (>=1.28.0,<1.29.0)"]
+rds = ["mypy-boto3-rds (>=1.28.0,<1.29.0)"]
+rds-data = ["mypy-boto3-rds-data (>=1.28.0,<1.29.0)"]
+redshift = ["mypy-boto3-redshift (>=1.28.0,<1.29.0)"]
+redshift-data = ["mypy-boto3-redshift-data (>=1.28.0,<1.29.0)"]
+redshift-serverless = ["mypy-boto3-redshift-serverless (>=1.28.0,<1.29.0)"]
+rekognition = ["mypy-boto3-rekognition (>=1.28.0,<1.29.0)"]
+resiliencehub = ["mypy-boto3-resiliencehub (>=1.28.0,<1.29.0)"]
+resource-explorer-2 = ["mypy-boto3-resource-explorer-2 (>=1.28.0,<1.29.0)"]
+resource-groups = ["mypy-boto3-resource-groups (>=1.28.0,<1.29.0)"]
+resourcegroupstaggingapi = ["mypy-boto3-resourcegroupstaggingapi (>=1.28.0,<1.29.0)"]
+robomaker = ["mypy-boto3-robomaker (>=1.28.0,<1.29.0)"]
+rolesanywhere = ["mypy-boto3-rolesanywhere (>=1.28.0,<1.29.0)"]
+route53 = ["mypy-boto3-route53 (>=1.28.0,<1.29.0)"]
+route53-recovery-cluster = ["mypy-boto3-route53-recovery-cluster (>=1.28.0,<1.29.0)"]
+route53-recovery-control-config = ["mypy-boto3-route53-recovery-control-config (>=1.28.0,<1.29.0)"]
+route53-recovery-readiness = ["mypy-boto3-route53-recovery-readiness (>=1.28.0,<1.29.0)"]
+route53domains = ["mypy-boto3-route53domains (>=1.28.0,<1.29.0)"]
+route53resolver = ["mypy-boto3-route53resolver (>=1.28.0,<1.29.0)"]
+rum = ["mypy-boto3-rum (>=1.28.0,<1.29.0)"]
+s3 = ["mypy-boto3-s3 (>=1.28.0,<1.29.0)"]
+s3control = ["mypy-boto3-s3control (>=1.28.0,<1.29.0)"]
+s3outposts = ["mypy-boto3-s3outposts (>=1.28.0,<1.29.0)"]
+sagemaker = ["mypy-boto3-sagemaker (>=1.28.0,<1.29.0)"]
+sagemaker-a2i-runtime = ["mypy-boto3-sagemaker-a2i-runtime (>=1.28.0,<1.29.0)"]
+sagemaker-edge = ["mypy-boto3-sagemaker-edge (>=1.28.0,<1.29.0)"]
+sagemaker-featurestore-runtime = ["mypy-boto3-sagemaker-featurestore-runtime (>=1.28.0,<1.29.0)"]
+sagemaker-geospatial = ["mypy-boto3-sagemaker-geospatial (>=1.28.0,<1.29.0)"]
+sagemaker-metrics = ["mypy-boto3-sagemaker-metrics (>=1.28.0,<1.29.0)"]
+sagemaker-runtime = ["mypy-boto3-sagemaker-runtime (>=1.28.0,<1.29.0)"]
+savingsplans = ["mypy-boto3-savingsplans (>=1.28.0,<1.29.0)"]
+scheduler = ["mypy-boto3-scheduler (>=1.28.0,<1.29.0)"]
+schemas = ["mypy-boto3-schemas (>=1.28.0,<1.29.0)"]
+sdb = ["mypy-boto3-sdb (>=1.28.0,<1.29.0)"]
+secretsmanager = ["mypy-boto3-secretsmanager (>=1.28.0,<1.29.0)"]
+securityhub = ["mypy-boto3-securityhub (>=1.28.0,<1.29.0)"]
+securitylake = ["mypy-boto3-securitylake (>=1.28.0,<1.29.0)"]
+serverlessrepo = ["mypy-boto3-serverlessrepo (>=1.28.0,<1.29.0)"]
+service-quotas = ["mypy-boto3-service-quotas (>=1.28.0,<1.29.0)"]
+servicecatalog = ["mypy-boto3-servicecatalog (>=1.28.0,<1.29.0)"]
+servicecatalog-appregistry = ["mypy-boto3-servicecatalog-appregistry (>=1.28.0,<1.29.0)"]
+servicediscovery = ["mypy-boto3-servicediscovery (>=1.28.0,<1.29.0)"]
+ses = ["mypy-boto3-ses (>=1.28.0,<1.29.0)"]
+sesv2 = ["mypy-boto3-sesv2 (>=1.28.0,<1.29.0)"]
+shield = ["mypy-boto3-shield (>=1.28.0,<1.29.0)"]
+signer = ["mypy-boto3-signer (>=1.28.0,<1.29.0)"]
+simspaceweaver = ["mypy-boto3-simspaceweaver (>=1.28.0,<1.29.0)"]
+sms = ["mypy-boto3-sms (>=1.28.0,<1.29.0)"]
+sms-voice = ["mypy-boto3-sms-voice (>=1.28.0,<1.29.0)"]
+snow-device-management = ["mypy-boto3-snow-device-management (>=1.28.0,<1.29.0)"]
+snowball = ["mypy-boto3-snowball (>=1.28.0,<1.29.0)"]
+sns = ["mypy-boto3-sns (>=1.28.0,<1.29.0)"]
+sqs = ["mypy-boto3-sqs (>=1.28.0,<1.29.0)"]
+ssm = ["mypy-boto3-ssm (>=1.28.0,<1.29.0)"]
+ssm-contacts = ["mypy-boto3-ssm-contacts (>=1.28.0,<1.29.0)"]
+ssm-incidents = ["mypy-boto3-ssm-incidents (>=1.28.0,<1.29.0)"]
+ssm-sap = ["mypy-boto3-ssm-sap (>=1.28.0,<1.29.0)"]
+sso = ["mypy-boto3-sso (>=1.28.0,<1.29.0)"]
+sso-admin = ["mypy-boto3-sso-admin (>=1.28.0,<1.29.0)"]
+sso-oidc = ["mypy-boto3-sso-oidc (>=1.28.0,<1.29.0)"]
+stepfunctions = ["mypy-boto3-stepfunctions (>=1.28.0,<1.29.0)"]
+storagegateway = ["mypy-boto3-storagegateway (>=1.28.0,<1.29.0)"]
+sts = ["mypy-boto3-sts (>=1.28.0,<1.29.0)"]
+support = ["mypy-boto3-support (>=1.28.0,<1.29.0)"]
+support-app = ["mypy-boto3-support-app (>=1.28.0,<1.29.0)"]
+swf = ["mypy-boto3-swf (>=1.28.0,<1.29.0)"]
+synthetics = ["mypy-boto3-synthetics (>=1.28.0,<1.29.0)"]
+textract = ["mypy-boto3-textract (>=1.28.0,<1.29.0)"]
+timestream-query = ["mypy-boto3-timestream-query (>=1.28.0,<1.29.0)"]
+timestream-write = ["mypy-boto3-timestream-write (>=1.28.0,<1.29.0)"]
+tnb = ["mypy-boto3-tnb (>=1.28.0,<1.29.0)"]
+transcribe = ["mypy-boto3-transcribe (>=1.28.0,<1.29.0)"]
+transfer = ["mypy-boto3-transfer (>=1.28.0,<1.29.0)"]
+translate = ["mypy-boto3-translate (>=1.28.0,<1.29.0)"]
+verifiedpermissions = ["mypy-boto3-verifiedpermissions (>=1.28.0,<1.29.0)"]
+voice-id = ["mypy-boto3-voice-id (>=1.28.0,<1.29.0)"]
+vpc-lattice = ["mypy-boto3-vpc-lattice (>=1.28.0,<1.29.0)"]
+waf = ["mypy-boto3-waf (>=1.28.0,<1.29.0)"]
+waf-regional = ["mypy-boto3-waf-regional (>=1.28.0,<1.29.0)"]
+wafv2 = ["mypy-boto3-wafv2 (>=1.28.0,<1.29.0)"]
+wellarchitected = ["mypy-boto3-wellarchitected (>=1.28.0,<1.29.0)"]
+wisdom = ["mypy-boto3-wisdom (>=1.28.0,<1.29.0)"]
+workdocs = ["mypy-boto3-workdocs (>=1.28.0,<1.29.0)"]
+worklink = ["mypy-boto3-worklink (>=1.28.0,<1.29.0)"]
+workmail = ["mypy-boto3-workmail (>=1.28.0,<1.29.0)"]
+workmailmessageflow = ["mypy-boto3-workmailmessageflow (>=1.28.0,<1.29.0)"]
+workspaces = ["mypy-boto3-workspaces (>=1.28.0,<1.29.0)"]
+workspaces-web = ["mypy-boto3-workspaces-web (>=1.28.0,<1.29.0)"]
+xray = ["mypy-boto3-xray (>=1.28.0,<1.29.0)"]
+
[[package]]
name = "botocore"
-version = "1.29.110"
+version = "1.31.2"
description = "Low-level, data-driven core of boto 3."
-category = "main"
optional = false
python-versions = ">= 3.7"
files = [
- {file = "botocore-1.29.110-py3-none-any.whl", hash = "sha256:39879fcc3d263513f9ba92cc5060b5a4dbe54f758a917be29c7a71132e34f399"},
- {file = "botocore-1.29.110.tar.gz", hash = "sha256:9d5054159782b19f27bff3e5a65bc494dc323255e889ea3abec002711a1fb0c0"},
+ {file = "botocore-1.31.2-py3-none-any.whl", hash = "sha256:d368ac0b58e2b9025b9c397e4a4f86d71788913ee619263506885a866a4f6811"},
+ {file = "botocore-1.31.2.tar.gz", hash = "sha256:67a475bec9e52d495a358b34e219ef7f62907e83b87e5bc712528f998bd46dab"},
]
[package.dependencies]
@@ -90,125 +510,235 @@ urllib3 = ">=1.25.4,<1.27"
[package.extras]
crt = ["awscrt (==0.16.9)"]
+[[package]]
+name = "botocore-stubs"
+version = "1.29.165"
+description = "Type annotations and code completion for botocore"
+optional = false
+python-versions = ">=3.7,<4.0"
+files = [
+ {file = "botocore_stubs-1.29.165-py3-none-any.whl", hash = "sha256:020de306ca1e18263e5a73b9142ec9901080f36d7c302ca53850483955e894ad"},
+ {file = "botocore_stubs-1.29.165.tar.gz", hash = "sha256:e9b23f54137bffbe7dcc08d9ca072172368cf92723aee34ec1de6e665f767c60"},
+]
+
+[package.dependencies]
+types-awscrt = "*"
+typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""}
+
[[package]]
name = "certifi"
-version = "2022.12.7"
+version = "2023.5.7"
description = "Python package for providing Mozilla's CA Bundle."
-category = "main"
optional = false
python-versions = ">=3.6"
files = [
- {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"},
- {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"},
+ {file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"},
+ {file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"},
+]
+
+[[package]]
+name = "cffi"
+version = "1.15.1"
+description = "Foreign Function Interface for Python calling C code."
+optional = false
+python-versions = "*"
+files = [
+ {file = "cffi-1.15.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2"},
+ {file = "cffi-1.15.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2"},
+ {file = "cffi-1.15.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914"},
+ {file = "cffi-1.15.1-cp27-cp27m-win32.whl", hash = "sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3"},
+ {file = "cffi-1.15.1-cp27-cp27m-win_amd64.whl", hash = "sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e"},
+ {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162"},
+ {file = "cffi-1.15.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b"},
+ {file = "cffi-1.15.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21"},
+ {file = "cffi-1.15.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185"},
+ {file = "cffi-1.15.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd"},
+ {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc"},
+ {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f"},
+ {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e"},
+ {file = "cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4"},
+ {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01"},
+ {file = "cffi-1.15.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e"},
+ {file = "cffi-1.15.1-cp310-cp310-win32.whl", hash = "sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2"},
+ {file = "cffi-1.15.1-cp310-cp310-win_amd64.whl", hash = "sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d"},
+ {file = "cffi-1.15.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac"},
+ {file = "cffi-1.15.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83"},
+ {file = "cffi-1.15.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9"},
+ {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c"},
+ {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325"},
+ {file = "cffi-1.15.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c"},
+ {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef"},
+ {file = "cffi-1.15.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8"},
+ {file = "cffi-1.15.1-cp311-cp311-win32.whl", hash = "sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d"},
+ {file = "cffi-1.15.1-cp311-cp311-win_amd64.whl", hash = "sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104"},
+ {file = "cffi-1.15.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7"},
+ {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6"},
+ {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d"},
+ {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a"},
+ {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405"},
+ {file = "cffi-1.15.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e"},
+ {file = "cffi-1.15.1-cp36-cp36m-win32.whl", hash = "sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf"},
+ {file = "cffi-1.15.1-cp36-cp36m-win_amd64.whl", hash = "sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497"},
+ {file = "cffi-1.15.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375"},
+ {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e"},
+ {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82"},
+ {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b"},
+ {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c"},
+ {file = "cffi-1.15.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426"},
+ {file = "cffi-1.15.1-cp37-cp37m-win32.whl", hash = "sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9"},
+ {file = "cffi-1.15.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045"},
+ {file = "cffi-1.15.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3"},
+ {file = "cffi-1.15.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a"},
+ {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5"},
+ {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca"},
+ {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02"},
+ {file = "cffi-1.15.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192"},
+ {file = "cffi-1.15.1-cp38-cp38-win32.whl", hash = "sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314"},
+ {file = "cffi-1.15.1-cp38-cp38-win_amd64.whl", hash = "sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5"},
+ {file = "cffi-1.15.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585"},
+ {file = "cffi-1.15.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0"},
+ {file = "cffi-1.15.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415"},
+ {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d"},
+ {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984"},
+ {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35"},
+ {file = "cffi-1.15.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27"},
+ {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76"},
+ {file = "cffi-1.15.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3"},
+ {file = "cffi-1.15.1-cp39-cp39-win32.whl", hash = "sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee"},
+ {file = "cffi-1.15.1-cp39-cp39-win_amd64.whl", hash = "sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c"},
+ {file = "cffi-1.15.1.tar.gz", hash = "sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9"},
+]
+
+[package.dependencies]
+pycparser = "*"
+
+[[package]]
+name = "cfn-lint"
+version = "0.77.10"
+description = "Checks CloudFormation templates for practices and behaviour that could potentially be improved"
+optional = false
+python-versions = ">=3.7, <=4.0, !=4.0"
+files = [
+ {file = "cfn-lint-0.77.10.tar.gz", hash = "sha256:c3bd6f5ae12641b6f99e100a4654e12448a9e16a0e0579afec8369709e12c904"},
+ {file = "cfn_lint-0.77.10-py3-none-any.whl", hash = "sha256:88ecb273a1a1770f206b957374cf33cb0b0779d14da482e9800e879897af9fa0"},
]
+[package.dependencies]
+aws-sam-translator = ">=1.68.0"
+jschema-to-python = ">=1.2.3,<1.3.0"
+jsonpatch = "*"
+jsonschema = ">=3.0,<5"
+junit-xml = ">=1.9,<2.0"
+networkx = ">=2.4,<4"
+pyyaml = ">5.4"
+regex = "*"
+sarif-om = ">=1.0.4,<1.1.0"
+sympy = ">=1.0.0"
+
[[package]]
name = "charset-normalizer"
-version = "3.1.0"
+version = "3.2.0"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
-category = "main"
optional = false
python-versions = ">=3.7.0"
files = [
- {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"},
- {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"},
- {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"},
- {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"},
- {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"},
- {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"},
- {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"},
+ {file = "charset-normalizer-3.2.0.tar.gz", hash = "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-win32.whl", hash = "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96"},
+ {file = "charset_normalizer-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-win32.whl", hash = "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1"},
+ {file = "charset_normalizer-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-win32.whl", hash = "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1"},
+ {file = "charset_normalizer-3.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-win32.whl", hash = "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706"},
+ {file = "charset_normalizer-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-win32.whl", hash = "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9"},
+ {file = "charset_normalizer-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80"},
+ {file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"},
]
[[package]]
name = "cli-test-helpers"
-version = "3.2.0"
+version = "3.4.0"
description = "Useful helpers for writing tests for your Python CLI program."
-category = "dev"
optional = false
python-versions = "*"
files = [
- {file = "cli-test-helpers-3.2.0.tar.gz", hash = "sha256:9c3bdfc4faae4a7340ef02321152f36ebc2012525acfb7272451c688b88a25e9"},
- {file = "cli_test_helpers-3.2.0-py3-none-any.whl", hash = "sha256:414fa232239c6733e8843fae653b5e10bb489cf875be94e029819755194baf17"},
+ {file = "cli-test-helpers-3.4.0.tar.gz", hash = "sha256:74eda958758bc11d0f3e63d6ebe857fd58a2d4dfee9db2cd3f87cfa72220cdc2"},
+ {file = "cli_test_helpers-3.4.0-py3-none-any.whl", hash = "sha256:8390692c2924791532ccdee1edb5ad996b76078f5cc457be6a22cf3566d16085"},
]
[[package]]
name = "click"
-version = "8.1.3"
+version = "8.1.4"
description = "Composable command line interface toolkit"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
- {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
+ {file = "click-8.1.4-py3-none-any.whl", hash = "sha256:2739815aaa5d2c986a88f1e9230c55e17f0caad3d958a5e13ad0797c166db9e3"},
+ {file = "click-8.1.4.tar.gz", hash = "sha256:b97d0c74955da062a7d4ef92fadb583806a585b2ea81958a81bd72726cbb8e37"},
]
[package.dependencies]
@@ -218,7 +748,6 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""}
name = "colorama"
version = "0.4.6"
description = "Cross-platform colored terminal text."
-category = "dev"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
files = [
@@ -228,63 +757,71 @@ files = [
[[package]]
name = "coverage"
-version = "7.2.3"
+version = "7.2.7"
description = "Code coverage measurement for Python"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "coverage-7.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e58c0d41d336569d63d1b113bd573db8363bc4146f39444125b7f8060e4e04f5"},
- {file = "coverage-7.2.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:344e714bd0fe921fc72d97404ebbdbf9127bac0ca1ff66d7b79efc143cf7c0c4"},
- {file = "coverage-7.2.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:974bc90d6f6c1e59ceb1516ab00cf1cdfbb2e555795d49fa9571d611f449bcb2"},
- {file = "coverage-7.2.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0743b0035d4b0e32bc1df5de70fba3059662ace5b9a2a86a9f894cfe66569013"},
- {file = "coverage-7.2.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d0391fb4cfc171ce40437f67eb050a340fdbd0f9f49d6353a387f1b7f9dd4fa"},
- {file = "coverage-7.2.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a42e1eff0ca9a7cb7dc9ecda41dfc7cbc17cb1d02117214be0561bd1134772b"},
- {file = "coverage-7.2.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:be19931a8dcbe6ab464f3339966856996b12a00f9fe53f346ab3be872d03e257"},
- {file = "coverage-7.2.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:72fcae5bcac3333a4cf3b8f34eec99cea1187acd55af723bcbd559adfdcb5535"},
- {file = "coverage-7.2.3-cp310-cp310-win32.whl", hash = "sha256:aeae2aa38395b18106e552833f2a50c27ea0000122bde421c31d11ed7e6f9c91"},
- {file = "coverage-7.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:83957d349838a636e768251c7e9979e899a569794b44c3728eaebd11d848e58e"},
- {file = "coverage-7.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dfd393094cd82ceb9b40df4c77976015a314b267d498268a076e940fe7be6b79"},
- {file = "coverage-7.2.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:182eb9ac3f2b4874a1f41b78b87db20b66da6b9cdc32737fbbf4fea0c35b23fc"},
- {file = "coverage-7.2.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bb1e77a9a311346294621be905ea8a2c30d3ad371fc15bb72e98bfcfae532df"},
- {file = "coverage-7.2.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca0f34363e2634deffd390a0fef1aa99168ae9ed2af01af4a1f5865e362f8623"},
- {file = "coverage-7.2.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55416d7385774285b6e2a5feca0af9652f7f444a4fa3d29d8ab052fafef9d00d"},
- {file = "coverage-7.2.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:06ddd9c0249a0546997fdda5a30fbcb40f23926df0a874a60a8a185bc3a87d93"},
- {file = "coverage-7.2.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fff5aaa6becf2c6a1699ae6a39e2e6fb0672c2d42eca8eb0cafa91cf2e9bd312"},
- {file = "coverage-7.2.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ea53151d87c52e98133eb8ac78f1206498c015849662ca8dc246255265d9c3c4"},
- {file = "coverage-7.2.3-cp311-cp311-win32.whl", hash = "sha256:8f6c930fd70d91ddee53194e93029e3ef2aabe26725aa3c2753df057e296b925"},
- {file = "coverage-7.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:fa546d66639d69aa967bf08156eb8c9d0cd6f6de84be9e8c9819f52ad499c910"},
- {file = "coverage-7.2.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b2317d5ed777bf5a033e83d4f1389fd4ef045763141d8f10eb09a7035cee774c"},
- {file = "coverage-7.2.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be9824c1c874b73b96288c6d3de793bf7f3a597770205068c6163ea1f326e8b9"},
- {file = "coverage-7.2.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2c3b2803e730dc2797a017335827e9da6da0e84c745ce0f552e66400abdfb9a1"},
- {file = "coverage-7.2.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f69770f5ca1994cb32c38965e95f57504d3aea96b6c024624fdd5bb1aa494a1"},
- {file = "coverage-7.2.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1127b16220f7bfb3f1049ed4a62d26d81970a723544e8252db0efde853268e21"},
- {file = "coverage-7.2.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:aa784405f0c640940595fa0f14064d8e84aff0b0f762fa18393e2760a2cf5841"},
- {file = "coverage-7.2.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3146b8e16fa60427e03884301bf8209221f5761ac754ee6b267642a2fd354c48"},
- {file = "coverage-7.2.3-cp37-cp37m-win32.whl", hash = "sha256:1fd78b911aea9cec3b7e1e2622c8018d51c0d2bbcf8faaf53c2497eb114911c1"},
- {file = "coverage-7.2.3-cp37-cp37m-win_amd64.whl", hash = "sha256:0f3736a5d34e091b0a611964c6262fd68ca4363df56185902528f0b75dbb9c1f"},
- {file = "coverage-7.2.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:981b4df72c93e3bc04478153df516d385317628bd9c10be699c93c26ddcca8ab"},
- {file = "coverage-7.2.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c0045f8f23a5fb30b2eb3b8a83664d8dc4fb58faddf8155d7109166adb9f2040"},
- {file = "coverage-7.2.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f760073fcf8f3d6933178d67754f4f2d4e924e321f4bb0dcef0424ca0215eba1"},
- {file = "coverage-7.2.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c86bd45d1659b1ae3d0ba1909326b03598affbc9ed71520e0ff8c31a993ad911"},
- {file = "coverage-7.2.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:172db976ae6327ed4728e2507daf8a4de73c7cc89796483e0a9198fd2e47b462"},
- {file = "coverage-7.2.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d2a3a6146fe9319926e1d477842ca2a63fe99af5ae690b1f5c11e6af074a6b5c"},
- {file = "coverage-7.2.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:f649dd53833b495c3ebd04d6eec58479454a1784987af8afb77540d6c1767abd"},
- {file = "coverage-7.2.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7c4ed4e9f3b123aa403ab424430b426a1992e6f4c8fd3cb56ea520446e04d152"},
- {file = "coverage-7.2.3-cp38-cp38-win32.whl", hash = "sha256:eb0edc3ce9760d2f21637766c3aa04822030e7451981ce569a1b3456b7053f22"},
- {file = "coverage-7.2.3-cp38-cp38-win_amd64.whl", hash = "sha256:63cdeaac4ae85a179a8d6bc09b77b564c096250d759eed343a89d91bce8b6367"},
- {file = "coverage-7.2.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:20d1a2a76bb4eb00e4d36b9699f9b7aba93271c9c29220ad4c6a9581a0320235"},
- {file = "coverage-7.2.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ea748802cc0de4de92ef8244dd84ffd793bd2e7be784cd8394d557a3c751e21"},
- {file = "coverage-7.2.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21b154aba06df42e4b96fc915512ab39595105f6c483991287021ed95776d934"},
- {file = "coverage-7.2.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd214917cabdd6f673a29d708574e9fbdb892cb77eb426d0eae3490d95ca7859"},
- {file = "coverage-7.2.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c2e58e45fe53fab81f85474e5d4d226eeab0f27b45aa062856c89389da2f0d9"},
- {file = "coverage-7.2.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:87ecc7c9a1a9f912e306997ffee020297ccb5ea388421fe62a2a02747e4d5539"},
- {file = "coverage-7.2.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:387065e420aed3c71b61af7e82c7b6bc1c592f7e3c7a66e9f78dd178699da4fe"},
- {file = "coverage-7.2.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ea3f5bc91d7d457da7d48c7a732beaf79d0c8131df3ab278e6bba6297e23c6c4"},
- {file = "coverage-7.2.3-cp39-cp39-win32.whl", hash = "sha256:ae7863a1d8db6a014b6f2ff9c1582ab1aad55a6d25bac19710a8df68921b6e30"},
- {file = "coverage-7.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:3f04becd4fcda03c0160d0da9c8f0c246bc78f2f7af0feea1ec0930e7c93fa4a"},
- {file = "coverage-7.2.3-pp37.pp38.pp39-none-any.whl", hash = "sha256:965ee3e782c7892befc25575fa171b521d33798132692df428a09efacaffe8d0"},
- {file = "coverage-7.2.3.tar.gz", hash = "sha256:d298c2815fa4891edd9abe5ad6e6cb4207104c7dd9fd13aea3fdebf6f9b91259"},
+ {file = "coverage-7.2.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d39b5b4f2a66ccae8b7263ac3c8170994b65266797fb96cbbfd3fb5b23921db8"},
+ {file = "coverage-7.2.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6d040ef7c9859bb11dfeb056ff5b3872436e3b5e401817d87a31e1750b9ae2fb"},
+ {file = "coverage-7.2.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba90a9563ba44a72fda2e85302c3abc71c5589cea608ca16c22b9804262aaeb6"},
+ {file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7d9405291c6928619403db1d10bd07888888ec1abcbd9748fdaa971d7d661b2"},
+ {file = "coverage-7.2.7-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31563e97dae5598556600466ad9beea39fb04e0229e61c12eaa206e0aa202063"},
+ {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ebba1cd308ef115925421d3e6a586e655ca5a77b5bf41e02eb0e4562a111f2d1"},
+ {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cb017fd1b2603ef59e374ba2063f593abe0fc45f2ad9abdde5b4d83bd922a353"},
+ {file = "coverage-7.2.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62a5c7dad11015c66fbb9d881bc4caa5b12f16292f857842d9d1871595f4495"},
+ {file = "coverage-7.2.7-cp310-cp310-win32.whl", hash = "sha256:ee57190f24fba796e36bb6d3aa8a8783c643d8fa9760c89f7a98ab5455fbf818"},
+ {file = "coverage-7.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:f75f7168ab25dd93110c8a8117a22450c19976afbc44234cbf71481094c1b850"},
+ {file = "coverage-7.2.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:06a9a2be0b5b576c3f18f1a241f0473575c4a26021b52b2a85263a00f034d51f"},
+ {file = "coverage-7.2.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5baa06420f837184130752b7c5ea0808762083bf3487b5038d68b012e5937dbe"},
+ {file = "coverage-7.2.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdec9e8cbf13a5bf63290fc6013d216a4c7232efb51548594ca3631a7f13c3a3"},
+ {file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52edc1a60c0d34afa421c9c37078817b2e67a392cab17d97283b64c5833f427f"},
+ {file = "coverage-7.2.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63426706118b7f5cf6bb6c895dc215d8a418d5952544042c8a2d9fe87fcf09cb"},
+ {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:afb17f84d56068a7c29f5fa37bfd38d5aba69e3304af08ee94da8ed5b0865833"},
+ {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:48c19d2159d433ccc99e729ceae7d5293fbffa0bdb94952d3579983d1c8c9d97"},
+ {file = "coverage-7.2.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0e1f928eaf5469c11e886fe0885ad2bf1ec606434e79842a879277895a50942a"},
+ {file = "coverage-7.2.7-cp311-cp311-win32.whl", hash = "sha256:33d6d3ea29d5b3a1a632b3c4e4f4ecae24ef170b0b9ee493883f2df10039959a"},
+ {file = "coverage-7.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:5b7540161790b2f28143191f5f8ec02fb132660ff175b7747b95dcb77ac26562"},
+ {file = "coverage-7.2.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f2f67fe12b22cd130d34d0ef79206061bfb5eda52feb6ce0dba0644e20a03cf4"},
+ {file = "coverage-7.2.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a342242fe22407f3c17f4b499276a02b01e80f861f1682ad1d95b04018e0c0d4"},
+ {file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:171717c7cb6b453aebac9a2ef603699da237f341b38eebfee9be75d27dc38e01"},
+ {file = "coverage-7.2.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49969a9f7ffa086d973d91cec8d2e31080436ef0fb4a359cae927e742abfaaa6"},
+ {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b46517c02ccd08092f4fa99f24c3b83d8f92f739b4657b0f146246a0ca6a831d"},
+ {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:a3d33a6b3eae87ceaefa91ffdc130b5e8536182cd6dfdbfc1aa56b46ff8c86de"},
+ {file = "coverage-7.2.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:976b9c42fb2a43ebf304fa7d4a310e5f16cc99992f33eced91ef6f908bd8f33d"},
+ {file = "coverage-7.2.7-cp312-cp312-win32.whl", hash = "sha256:8de8bb0e5ad103888d65abef8bca41ab93721647590a3f740100cd65c3b00511"},
+ {file = "coverage-7.2.7-cp312-cp312-win_amd64.whl", hash = "sha256:9e31cb64d7de6b6f09702bb27c02d1904b3aebfca610c12772452c4e6c21a0d3"},
+ {file = "coverage-7.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:58c2ccc2f00ecb51253cbe5d8d7122a34590fac9646a960d1430d5b15321d95f"},
+ {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d22656368f0e6189e24722214ed8d66b8022db19d182927b9a248a2a8a2f67eb"},
+ {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a895fcc7b15c3fc72beb43cdcbdf0ddb7d2ebc959edac9cef390b0d14f39f8a9"},
+ {file = "coverage-7.2.7-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84606b74eb7de6ff581a7915e2dab7a28a0517fbe1c9239eb227e1354064dcd"},
+ {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:0a5f9e1dbd7fbe30196578ca36f3fba75376fb99888c395c5880b355e2875f8a"},
+ {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:419bfd2caae268623dd469eff96d510a920c90928b60f2073d79f8fe2bbc5959"},
+ {file = "coverage-7.2.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2aee274c46590717f38ae5e4650988d1af340fe06167546cc32fe2f58ed05b02"},
+ {file = "coverage-7.2.7-cp37-cp37m-win32.whl", hash = "sha256:61b9a528fb348373c433e8966535074b802c7a5d7f23c4f421e6c6e2f1697a6f"},
+ {file = "coverage-7.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:b1c546aca0ca4d028901d825015dc8e4d56aac4b541877690eb76490f1dc8ed0"},
+ {file = "coverage-7.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:54b896376ab563bd38453cecb813c295cf347cf5906e8b41d340b0321a5433e5"},
+ {file = "coverage-7.2.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3d376df58cc111dc8e21e3b6e24606b5bb5dee6024f46a5abca99124b2229ef5"},
+ {file = "coverage-7.2.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e330fc79bd7207e46c7d7fd2bb4af2963f5f635703925543a70b99574b0fea9"},
+ {file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e9d683426464e4a252bf70c3498756055016f99ddaec3774bf368e76bbe02b6"},
+ {file = "coverage-7.2.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d13c64ee2d33eccf7437961b6ea7ad8673e2be040b4f7fd4fd4d4d28d9ccb1e"},
+ {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7aa5f8a41217360e600da646004f878250a0d6738bcdc11a0a39928d7dc2050"},
+ {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fa03bce9bfbeeef9f3b160a8bed39a221d82308b4152b27d82d8daa7041fee5"},
+ {file = "coverage-7.2.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:245167dd26180ab4c91d5e1496a30be4cd721a5cf2abf52974f965f10f11419f"},
+ {file = "coverage-7.2.7-cp38-cp38-win32.whl", hash = "sha256:d2c2db7fd82e9b72937969bceac4d6ca89660db0a0967614ce2481e81a0b771e"},
+ {file = "coverage-7.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:2e07b54284e381531c87f785f613b833569c14ecacdcb85d56b25c4622c16c3c"},
+ {file = "coverage-7.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:537891ae8ce59ef63d0123f7ac9e2ae0fc8b72c7ccbe5296fec45fd68967b6c9"},
+ {file = "coverage-7.2.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06fb182e69f33f6cd1d39a6c597294cff3143554b64b9825d1dc69d18cc2fff2"},
+ {file = "coverage-7.2.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:201e7389591af40950a6480bd9edfa8ed04346ff80002cec1a66cac4549c1ad7"},
+ {file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f6951407391b639504e3b3be51b7ba5f3528adbf1a8ac3302b687ecababf929e"},
+ {file = "coverage-7.2.7-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f48351d66575f535669306aa7d6d6f71bc43372473b54a832222803eb956fd1"},
+ {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b29019c76039dc3c0fd815c41392a044ce555d9bcdd38b0fb60fb4cd8e475ba9"},
+ {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:81c13a1fc7468c40f13420732805a4c38a105d89848b7c10af65a90beff25250"},
+ {file = "coverage-7.2.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:975d70ab7e3c80a3fe86001d8751f6778905ec723f5b110aed1e450da9d4b7f2"},
+ {file = "coverage-7.2.7-cp39-cp39-win32.whl", hash = "sha256:7ee7d9d4822c8acc74a5e26c50604dff824710bc8de424904c0982e25c39c6cb"},
+ {file = "coverage-7.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:eb393e5ebc85245347950143969b241d08b52b88a3dc39479822e073a1a8eb27"},
+ {file = "coverage-7.2.7-pp37.pp38.pp39-none-any.whl", hash = "sha256:b7b4c971f05e6ae490fef852c218b0e79d4e52f79ef0c8475566584a8fb3e01d"},
+ {file = "coverage-7.2.7.tar.gz", hash = "sha256:924d94291ca674905fe9481f12294eb11f2d3d3fd1adb20314ba89e94f44ed59"},
]
[package.dependencies]
@@ -293,26 +830,135 @@ tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.1
[package.extras]
toml = ["tomli"]
+[[package]]
+name = "cryptography"
+version = "41.0.2"
+description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "cryptography-41.0.2-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:01f1d9e537f9a15b037d5d9ee442b8c22e3ae11ce65ea1f3316a41c78756b711"},
+ {file = "cryptography-41.0.2-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:079347de771f9282fbfe0e0236c716686950c19dee1b76240ab09ce1624d76d7"},
+ {file = "cryptography-41.0.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:439c3cc4c0d42fa999b83ded80a9a1fb54d53c58d6e59234cfe97f241e6c781d"},
+ {file = "cryptography-41.0.2-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f14ad275364c8b4e525d018f6716537ae7b6d369c094805cae45300847e0894f"},
+ {file = "cryptography-41.0.2-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:84609ade00a6ec59a89729e87a503c6e36af98ddcd566d5f3be52e29ba993182"},
+ {file = "cryptography-41.0.2-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:49c3222bb8f8e800aead2e376cbef687bc9e3cb9b58b29a261210456a7783d83"},
+ {file = "cryptography-41.0.2-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:d73f419a56d74fef257955f51b18d046f3506270a5fd2ac5febbfa259d6c0fa5"},
+ {file = "cryptography-41.0.2-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:2a034bf7d9ca894720f2ec1d8b7b5832d7e363571828037f9e0c4f18c1b58a58"},
+ {file = "cryptography-41.0.2-cp37-abi3-win32.whl", hash = "sha256:d124682c7a23c9764e54ca9ab5b308b14b18eba02722b8659fb238546de83a76"},
+ {file = "cryptography-41.0.2-cp37-abi3-win_amd64.whl", hash = "sha256:9c3fe6534d59d071ee82081ca3d71eed3210f76ebd0361798c74abc2bcf347d4"},
+ {file = "cryptography-41.0.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a719399b99377b218dac6cf547b6ec54e6ef20207b6165126a280b0ce97e0d2a"},
+ {file = "cryptography-41.0.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:182be4171f9332b6741ee818ec27daff9fb00349f706629f5cbf417bd50e66fd"},
+ {file = "cryptography-41.0.2-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:7a9a3bced53b7f09da251685224d6a260c3cb291768f54954e28f03ef14e3766"},
+ {file = "cryptography-41.0.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:f0dc40e6f7aa37af01aba07277d3d64d5a03dc66d682097541ec4da03cc140ee"},
+ {file = "cryptography-41.0.2-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:674b669d5daa64206c38e507808aae49904c988fa0a71c935e7006a3e1e83831"},
+ {file = "cryptography-41.0.2-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:7af244b012711a26196450d34f483357e42aeddb04128885d95a69bd8b14b69b"},
+ {file = "cryptography-41.0.2-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9b6d717393dbae53d4e52684ef4f022444fc1cce3c48c38cb74fca29e1f08eaa"},
+ {file = "cryptography-41.0.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:192255f539d7a89f2102d07d7375b1e0a81f7478925b3bc2e0549ebf739dae0e"},
+ {file = "cryptography-41.0.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f772610fe364372de33d76edcd313636a25684edb94cee53fd790195f5989d14"},
+ {file = "cryptography-41.0.2-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:b332cba64d99a70c1e0836902720887fb4529ea49ea7f5462cf6640e095e11d2"},
+ {file = "cryptography-41.0.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9a6673c1828db6270b76b22cc696f40cde9043eb90373da5c2f8f2158957f42f"},
+ {file = "cryptography-41.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:342f3767e25876751e14f8459ad85e77e660537ca0a066e10e75df9c9e9099f0"},
+ {file = "cryptography-41.0.2.tar.gz", hash = "sha256:7d230bf856164de164ecb615ccc14c7fc6de6906ddd5b491f3af90d3514c925c"},
+]
+
+[package.dependencies]
+cffi = ">=1.12"
+
+[package.extras]
+docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"]
+docstest = ["pyenchant (>=1.6.11)", "sphinxcontrib-spelling (>=4.0.1)", "twine (>=1.12.0)"]
+nox = ["nox"]
+pep8test = ["black", "check-sdist", "mypy", "ruff"]
+sdist = ["build"]
+ssh = ["bcrypt (>=3.1.5)"]
+test = ["pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"]
+test-randomorder = ["pytest-randomly"]
+
+[[package]]
+name = "docker"
+version = "6.1.3"
+description = "A Python library for the Docker Engine API."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "docker-6.1.3-py3-none-any.whl", hash = "sha256:aecd2277b8bf8e506e484f6ab7aec39abe0038e29fa4a6d3ba86c3fe01844ed9"},
+ {file = "docker-6.1.3.tar.gz", hash = "sha256:aa6d17830045ba5ef0168d5eaa34d37beeb113948c413affe1d5991fc11f9a20"},
+]
+
+[package.dependencies]
+packaging = ">=14.0"
+pywin32 = {version = ">=304", markers = "sys_platform == \"win32\""}
+requests = ">=2.26.0"
+urllib3 = ">=1.26.0"
+websocket-client = ">=0.32.0"
+
+[package.extras]
+ssh = ["paramiko (>=2.4.3)"]
+
+[[package]]
+name = "ecdsa"
+version = "0.18.0"
+description = "ECDSA cryptographic signature library (pure python)"
+optional = false
+python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+files = [
+ {file = "ecdsa-0.18.0-py2.py3-none-any.whl", hash = "sha256:80600258e7ed2f16b9aa1d7c295bd70194109ad5a30fdee0eaeefef1d4c559dd"},
+ {file = "ecdsa-0.18.0.tar.gz", hash = "sha256:190348041559e21b22a1d65cee485282ca11a6f81d503fddb84d5017e9ed1e49"},
+]
+
+[package.dependencies]
+six = ">=1.9.0"
+
+[package.extras]
+gmpy = ["gmpy"]
+gmpy2 = ["gmpy2"]
+
[[package]]
name = "exceptiongroup"
-version = "1.1.1"
+version = "1.1.2"
description = "Backport of PEP 654 (exception groups)"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
- {file = "exceptiongroup-1.1.1-py3-none-any.whl", hash = "sha256:232c37c63e4f682982c8b6459f33a8981039e5fb8756b2074364e5055c498c9e"},
- {file = "exceptiongroup-1.1.1.tar.gz", hash = "sha256:d484c3090ba2889ae2928419117447a14daf3c1231d5e30d0aae34f354f01785"},
+ {file = "exceptiongroup-1.1.2-py3-none-any.whl", hash = "sha256:e346e69d186172ca7cf029c8c1d16235aa0e04035e5750b4b95039e65204328f"},
+ {file = "exceptiongroup-1.1.2.tar.gz", hash = "sha256:12c3e887d6485d16943a309616de20ae5582633e0a2eda17f4e10fd61c1e8af5"},
]
[package.extras]
test = ["pytest (>=6)"]
+[[package]]
+name = "flake8"
+version = "6.0.0"
+description = "the modular source code checker: pep8 pyflakes and co"
+optional = false
+python-versions = ">=3.8.1"
+files = [
+ {file = "flake8-6.0.0-py2.py3-none-any.whl", hash = "sha256:3833794e27ff64ea4e9cf5d410082a8b97ff1a06c16aa3d2027339cd0f1195c7"},
+ {file = "flake8-6.0.0.tar.gz", hash = "sha256:c61007e76655af75e6785a931f452915b371dc48f56efd765247c8fe68f2b181"},
+]
+
+[package.dependencies]
+mccabe = ">=0.7.0,<0.8.0"
+pycodestyle = ">=2.10.0,<2.11.0"
+pyflakes = ">=3.0.0,<3.1.0"
+
+[[package]]
+name = "graphql-core"
+version = "3.2.3"
+description = "GraphQL implementation for Python, a port of GraphQL.js, the JavaScript reference implementation for GraphQL."
+optional = false
+python-versions = ">=3.6,<4"
+files = [
+ {file = "graphql-core-3.2.3.tar.gz", hash = "sha256:06d2aad0ac723e35b1cb47885d3e5c45e956a53bc1b209a9fc5369007fe46676"},
+ {file = "graphql_core-3.2.3-py3-none-any.whl", hash = "sha256:5766780452bd5ec8ba133f8bf287dc92713e3868ddd83aee4faab9fc3e303dc3"},
+]
+
[[package]]
name = "idna"
version = "3.4"
description = "Internationalized Domain Names in Applications (IDNA)"
-category = "main"
optional = false
python-versions = ">=3.5"
files = [
@@ -320,11 +966,28 @@ files = [
{file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
]
+[[package]]
+name = "importlib-resources"
+version = "5.13.0"
+description = "Read resources from Python packages"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "importlib_resources-5.13.0-py3-none-any.whl", hash = "sha256:9f7bd0c97b79972a6cce36a366356d16d5e13b09679c11a58f1014bfdf8e64b2"},
+ {file = "importlib_resources-5.13.0.tar.gz", hash = "sha256:82d5c6cca930697dbbd86c93333bb2c2e72861d4789a11c2662b933e5ad2b528"},
+]
+
+[package.dependencies]
+zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""}
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
+testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"]
+
[[package]]
name = "iniconfig"
version = "2.0.0"
description = "brain-dead simple config-ini parsing"
-category = "dev"
optional = false
python-versions = ">=3.7"
files = [
@@ -332,11 +995,44 @@ files = [
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
]
+[[package]]
+name = "isort"
+version = "5.12.0"
+description = "A Python utility / library to sort Python imports."
+optional = false
+python-versions = ">=3.8.0"
+files = [
+ {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"},
+ {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"},
+]
+
+[package.extras]
+colors = ["colorama (>=0.4.3)"]
+pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"]
+plugins = ["setuptools"]
+requirements-deprecated-finder = ["pip-api", "pipreqs"]
+
+[[package]]
+name = "jinja2"
+version = "3.1.2"
+description = "A very fast and expressive template engine."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
+ {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
+]
+
+[package.dependencies]
+MarkupSafe = ">=2.0"
+
+[package.extras]
+i18n = ["Babel (>=2.7)"]
+
[[package]]
name = "jmespath"
version = "1.0.1"
description = "JSON Matching Expressions"
-category = "main"
optional = false
python-versions = ">=3.7"
files = [
@@ -345,224 +1041,1459 @@ files = [
]
[[package]]
-name = "mypy-extensions"
-version = "1.0.0"
-description = "Type system extensions for programs checked with the mypy type checker."
-category = "dev"
+name = "jschema-to-python"
+version = "1.2.3"
+description = "Generate source code for Python classes from a JSON schema."
optional = false
-python-versions = ">=3.5"
+python-versions = ">= 2.7"
files = [
- {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
- {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
+ {file = "jschema_to_python-1.2.3-py3-none-any.whl", hash = "sha256:8a703ca7604d42d74b2815eecf99a33359a8dccbb80806cce386d5e2dd992b05"},
+ {file = "jschema_to_python-1.2.3.tar.gz", hash = "sha256:76ff14fe5d304708ccad1284e4b11f96a658949a31ee7faed9e0995279549b91"},
]
+[package.dependencies]
+attrs = "*"
+jsonpickle = "*"
+pbr = "*"
+
[[package]]
-name = "packaging"
-version = "23.0"
-description = "Core utilities for Python packages"
-category = "dev"
+name = "jsondiff"
+version = "2.0.0"
+description = "Diff JSON and JSON-like structures in Python"
optional = false
-python-versions = ">=3.7"
+python-versions = "*"
files = [
- {file = "packaging-23.0-py3-none-any.whl", hash = "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2"},
- {file = "packaging-23.0.tar.gz", hash = "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97"},
+ {file = "jsondiff-2.0.0-py3-none-any.whl", hash = "sha256:689841d66273fc88fc79f7d33f4c074774f4f214b6466e3aff0e5adaf889d1e0"},
+ {file = "jsondiff-2.0.0.tar.gz", hash = "sha256:2795844ef075ec8a2b8d385c4d59f5ea48b08e7180fce3cb2787be0db00b1fb4"},
]
[[package]]
-name = "pathspec"
-version = "0.11.1"
-description = "Utility library for gitignore style pattern matching of file paths."
-category = "dev"
+name = "jsonpatch"
+version = "1.33"
+description = "Apply JSON-Patches (RFC 6902)"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*"
files = [
- {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"},
- {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"},
+ {file = "jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade"},
+ {file = "jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c"},
]
+[package.dependencies]
+jsonpointer = ">=1.9"
+
[[package]]
-name = "platformdirs"
-version = "3.2.0"
-description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
-category = "dev"
+name = "jsonpickle"
+version = "3.0.1"
+description = "Python library for serializing any arbitrary object graph into JSON"
optional = false
python-versions = ">=3.7"
files = [
- {file = "platformdirs-3.2.0-py3-none-any.whl", hash = "sha256:ebe11c0d7a805086e99506aa331612429a72ca7cd52a1f0d277dc4adc20cb10e"},
- {file = "platformdirs-3.2.0.tar.gz", hash = "sha256:d5b638ca397f25f979350ff789db335903d7ea010ab28903f57b27e1b16c2b08"},
+ {file = "jsonpickle-3.0.1-py2.py3-none-any.whl", hash = "sha256:130d8b293ea0add3845de311aaba55e6d706d0bb17bc123bd2c8baf8a39ac77c"},
+ {file = "jsonpickle-3.0.1.tar.gz", hash = "sha256:032538804795e73b94ead410800ac387fdb6de98f8882ac957fcd247e3a85200"},
]
[package.extras]
-docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=6.1.3)", "sphinx-autodoc-typehints (>=1.22,!=1.23.4)"]
-test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.2.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
+docs = ["jaraco.packaging (>=3.2)", "rst.linker (>=1.9)", "sphinx"]
+testing = ["ecdsa", "feedparser", "gmpy2", "numpy", "pandas", "pymongo", "pytest (>=3.5,!=3.7.3)", "pytest-black-multipy", "pytest-checkdocs (>=1.2.3)", "pytest-cov", "pytest-flake8 (>=1.1.1)", "scikit-learn", "sqlalchemy"]
+testing-libs = ["simplejson", "ujson"]
[[package]]
-name = "pluggy"
-version = "1.0.0"
-description = "plugin and hook calling mechanisms for python"
-category = "dev"
+name = "jsonpointer"
+version = "2.4"
+description = "Identify specific nodes in a JSON document (RFC 6901)"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*"
files = [
- {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
- {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
+ {file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"},
+ {file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"},
]
-[package.extras]
-dev = ["pre-commit", "tox"]
-testing = ["pytest", "pytest-benchmark"]
-
[[package]]
-name = "pytest"
-version = "7.3.0"
-description = "pytest: simple powerful testing with Python"
-category = "dev"
+name = "jsonschema"
+version = "4.18.1"
+description = "An implementation of JSON Schema validation for Python"
optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
files = [
- {file = "pytest-7.3.0-py3-none-any.whl", hash = "sha256:933051fa1bfbd38a21e73c3960cebdad4cf59483ddba7696c48509727e17f201"},
- {file = "pytest-7.3.0.tar.gz", hash = "sha256:58ecc27ebf0ea643ebfdf7fb1249335da761a00c9f955bcd922349bcb68ee57d"},
+ {file = "jsonschema-4.18.1-py3-none-any.whl", hash = "sha256:e5fde3cb78f3be8cf49150390ee4efbb8e73c46ea467d42cd4ec16e364495eb3"},
+ {file = "jsonschema-4.18.1.tar.gz", hash = "sha256:b5896514b46cc9283e9951bfebf51cc72fa3eab229919c0469f94e11b4387776"},
]
[package.dependencies]
-colorama = {version = "*", markers = "sys_platform == \"win32\""}
-exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
-iniconfig = "*"
-packaging = "*"
-pluggy = ">=0.12,<2.0"
-tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
+attrs = ">=22.2.0"
+importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""}
+jsonschema-specifications = ">=2023.03.6"
+pkgutil-resolve-name = {version = ">=1.3.10", markers = "python_version < \"3.9\""}
+referencing = ">=0.28.4"
+rpds-py = ">=0.7.1"
[package.extras]
-testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
+format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"]
+format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"]
[[package]]
-name = "pytest-cov"
-version = "4.0.0"
-description = "Pytest plugin for measuring coverage."
-category = "dev"
+name = "jsonschema-spec"
+version = "0.2.3"
+description = "JSONSchema Spec with object-oriented paths"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.8.0,<4.0.0"
files = [
- {file = "pytest-cov-4.0.0.tar.gz", hash = "sha256:996b79efde6433cdbd0088872dbc5fb3ed7fe1578b68cdbba634f14bb8dd0470"},
- {file = "pytest_cov-4.0.0-py3-none-any.whl", hash = "sha256:2feb1b751d66a8bd934e5edfa2e961d11309dc37b73b0eabe73b5945fee20f6b"},
+ {file = "jsonschema_spec-0.2.3-py3-none-any.whl", hash = "sha256:ee005ddeca73229560ac2b8f1849590929c4b2cd17a932b229b03566e517f2a6"},
+ {file = "jsonschema_spec-0.2.3.tar.gz", hash = "sha256:e01b8b100f0676177b0b39027a5cab7e7a16ce4316a3d0d15e576293d954fafc"},
]
[package.dependencies]
-coverage = {version = ">=5.2.1", extras = ["toml"]}
-pytest = ">=4.6"
-
-[package.extras]
-testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"]
+pathable = ">=0.4.1,<0.5.0"
+PyYAML = ">=5.1"
+referencing = ">=0.28.0,<0.30.0"
+requests = ">=2.31.0,<3.0.0"
[[package]]
-name = "python-dateutil"
-version = "2.8.2"
-description = "Extensions to the standard Python datetime module"
-category = "main"
+name = "jsonschema-specifications"
+version = "2023.6.1"
+description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry"
optional = false
-python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
+python-versions = ">=3.8"
files = [
- {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
- {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
+ {file = "jsonschema_specifications-2023.6.1-py3-none-any.whl", hash = "sha256:3d2b82663aff01815f744bb5c7887e2121a63399b49b104a3c96145474d091d7"},
+ {file = "jsonschema_specifications-2023.6.1.tar.gz", hash = "sha256:ca1c4dd059a9e7b34101cf5b3ab7ff1d18b139f35950d598d629837ef66e8f28"},
]
[package.dependencies]
-six = ">=1.5"
+importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""}
+referencing = ">=0.28.0"
[[package]]
-name = "requests"
-version = "2.28.2"
-description = "Python HTTP for Humans."
-category = "main"
+name = "junit-xml"
+version = "1.9"
+description = "Creates JUnit XML test result documents that can be read by tools such as Jenkins"
optional = false
-python-versions = ">=3.7, <4"
+python-versions = "*"
files = [
- {file = "requests-2.28.2-py3-none-any.whl", hash = "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"},
- {file = "requests-2.28.2.tar.gz", hash = "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"},
+ {file = "junit-xml-1.9.tar.gz", hash = "sha256:de16a051990d4e25a3982b2dd9e89d671067548718866416faec14d9de56db9f"},
+ {file = "junit_xml-1.9-py2.py3-none-any.whl", hash = "sha256:ec5ca1a55aefdd76d28fcc0b135251d156c7106fa979686a4b48d62b761b4732"},
]
[package.dependencies]
-certifi = ">=2017.4.17"
-charset-normalizer = ">=2,<4"
-idna = ">=2.5,<4"
-urllib3 = ">=1.21.1,<1.27"
+six = "*"
-[package.extras]
-socks = ["PySocks (>=1.5.6,!=1.5.7)"]
-use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
+[[package]]
+name = "lazy-object-proxy"
+version = "1.9.0"
+description = "A fast and thorough lazy object proxy."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "lazy-object-proxy-1.9.0.tar.gz", hash = "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae"},
+ {file = "lazy_object_proxy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7"},
+ {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4"},
+ {file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd"},
+ {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701"},
+ {file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46"},
+ {file = "lazy_object_proxy-1.9.0-cp310-cp310-win32.whl", hash = "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455"},
+ {file = "lazy_object_proxy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e"},
+ {file = "lazy_object_proxy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07"},
+ {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a"},
+ {file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59"},
+ {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4"},
+ {file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9"},
+ {file = "lazy_object_proxy-1.9.0-cp311-cp311-win32.whl", hash = "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586"},
+ {file = "lazy_object_proxy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb"},
+ {file = "lazy_object_proxy-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e"},
+ {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8"},
+ {file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2"},
+ {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8"},
+ {file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda"},
+ {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win32.whl", hash = "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734"},
+ {file = "lazy_object_proxy-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671"},
+ {file = "lazy_object_proxy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63"},
+ {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171"},
+ {file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be"},
+ {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30"},
+ {file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11"},
+ {file = "lazy_object_proxy-1.9.0-cp38-cp38-win32.whl", hash = "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82"},
+ {file = "lazy_object_proxy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b"},
+ {file = "lazy_object_proxy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b"},
+ {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4"},
+ {file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006"},
+ {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494"},
+ {file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382"},
+ {file = "lazy_object_proxy-1.9.0-cp39-cp39-win32.whl", hash = "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821"},
+ {file = "lazy_object_proxy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f"},
+]
[[package]]
-name = "s3transfer"
-version = "0.6.0"
-description = "An Amazon S3 Transfer Manager"
-category = "main"
+name = "markupsafe"
+version = "2.1.3"
+description = "Safely add untrusted strings to HTML/XML markup."
optional = false
-python-versions = ">= 3.7"
+python-versions = ">=3.7"
+files = [
+ {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"},
+ {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"},
+ {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"},
+ {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"},
+ {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"},
+ {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"},
+ {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"},
+]
+
+[[package]]
+name = "mccabe"
+version = "0.7.0"
+description = "McCabe checker, plugin for flake8"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"},
+ {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"},
+]
+
+[[package]]
+name = "moto"
+version = "4.1.12"
+description = ""
+optional = false
+python-versions = ">=3.7"
files = [
- {file = "s3transfer-0.6.0-py3-none-any.whl", hash = "sha256:06176b74f3a15f61f1b4f25a1fc29a4429040b7647133a463da8fa5bd28d5ecd"},
- {file = "s3transfer-0.6.0.tar.gz", hash = "sha256:2ed07d3866f523cc561bf4a00fc5535827981b117dd7876f036b0c1aca42c947"},
+ {file = "moto-4.1.12-py2.py3-none-any.whl", hash = "sha256:6f40141ff2f3a309c19faa169433afdf48d28733d328b08a843021ae36f005d9"},
+ {file = "moto-4.1.12.tar.gz", hash = "sha256:25577e4cf55f05235f4efe78bcfeb5a7704fb75c16b426a5de2fc1e6b7b8545b"},
]
[package.dependencies]
-botocore = ">=1.12.36,<2.0a.0"
+aws-xray-sdk = {version = ">=0.93,<0.96 || >0.96", optional = true, markers = "extra == \"cloudformation\""}
+boto3 = ">=1.9.201"
+botocore = ">=1.12.201"
+cfn-lint = {version = ">=0.40.0", optional = true, markers = "extra == \"cloudformation\""}
+cryptography = ">=3.3.1"
+docker = {version = ">=3.0.0", optional = true, markers = "extra == \"cloudformation\""}
+ecdsa = {version = "!=0.15", optional = true, markers = "extra == \"cloudformation\""}
+graphql-core = {version = "*", optional = true, markers = "extra == \"cloudformation\""}
+Jinja2 = ">=2.10.1"
+jsondiff = {version = ">=1.1.2", optional = true, markers = "extra == \"cloudformation\""}
+openapi-spec-validator = {version = ">=0.2.8", optional = true, markers = "extra == \"cloudformation\""}
+py-partiql-parser = {version = "0.3.3", optional = true, markers = "extra == \"cloudformation\""}
+pyparsing = {version = ">=3.0.7", optional = true, markers = "extra == \"cloudformation\""}
+python-dateutil = ">=2.1,<3.0.0"
+python-jose = {version = ">=3.1.0,<4.0.0", extras = ["cryptography"], optional = true, markers = "extra == \"cloudformation\""}
+PyYAML = {version = ">=5.1", optional = true, markers = "extra == \"cloudformation\""}
+requests = ">=2.5"
+responses = ">=0.13.0"
+setuptools = {version = "*", optional = true, markers = "extra == \"cloudformation\""}
+sshpubkeys = {version = ">=3.1.0", optional = true, markers = "extra == \"cloudformation\""}
+werkzeug = ">=0.5,<2.2.0 || >2.2.0,<2.2.1 || >2.2.1"
+xmltodict = "*"
[package.extras]
-crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"]
+all = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "graphql-core", "jsondiff (>=1.1.2)", "openapi-spec-validator (>=0.2.8)", "py-partiql-parser (==0.3.3)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"]
+apigateway = ["PyYAML (>=5.1)", "ecdsa (!=0.15)", "openapi-spec-validator (>=0.2.8)", "python-jose[cryptography] (>=3.1.0,<4.0.0)"]
+apigatewayv2 = ["PyYAML (>=5.1)"]
+appsync = ["graphql-core"]
+awslambda = ["docker (>=3.0.0)"]
+batch = ["docker (>=3.0.0)"]
+cloudformation = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "graphql-core", "jsondiff (>=1.1.2)", "openapi-spec-validator (>=0.2.8)", "py-partiql-parser (==0.3.3)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"]
+cognitoidp = ["ecdsa (!=0.15)", "python-jose[cryptography] (>=3.1.0,<4.0.0)"]
+ds = ["sshpubkeys (>=3.1.0)"]
+dynamodb = ["docker (>=3.0.0)", "py-partiql-parser (==0.3.3)"]
+dynamodbstreams = ["docker (>=3.0.0)", "py-partiql-parser (==0.3.3)"]
+ebs = ["sshpubkeys (>=3.1.0)"]
+ec2 = ["sshpubkeys (>=3.1.0)"]
+efs = ["sshpubkeys (>=3.1.0)"]
+eks = ["sshpubkeys (>=3.1.0)"]
+glue = ["pyparsing (>=3.0.7)"]
+iotdata = ["jsondiff (>=1.1.2)"]
+route53resolver = ["sshpubkeys (>=3.1.0)"]
+s3 = ["PyYAML (>=5.1)", "py-partiql-parser (==0.3.3)"]
+server = ["PyYAML (>=5.1)", "aws-xray-sdk (>=0.93,!=0.96)", "cfn-lint (>=0.40.0)", "docker (>=3.0.0)", "ecdsa (!=0.15)", "flask (!=2.2.0,!=2.2.1)", "flask-cors", "graphql-core", "jsondiff (>=1.1.2)", "openapi-spec-validator (>=0.2.8)", "py-partiql-parser (==0.3.3)", "pyparsing (>=3.0.7)", "python-jose[cryptography] (>=3.1.0,<4.0.0)", "setuptools", "sshpubkeys (>=3.1.0)"]
+ssm = ["PyYAML (>=5.1)"]
+xray = ["aws-xray-sdk (>=0.93,!=0.96)", "setuptools"]
[[package]]
-name = "six"
-version = "1.16.0"
-description = "Python 2 and 3 compatibility utilities"
-category = "main"
+name = "mpmath"
+version = "1.3.0"
+description = "Python library for arbitrary-precision floating-point arithmetic"
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
+python-versions = "*"
files = [
- {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
- {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
+ {file = "mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c"},
+ {file = "mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f"},
]
+[package.extras]
+develop = ["codecov", "pycodestyle", "pytest (>=4.6)", "pytest-cov", "wheel"]
+docs = ["sphinx"]
+gmpy = ["gmpy2 (>=2.1.0a4)"]
+tests = ["pytest (>=4.6)"]
+
[[package]]
-name = "tomli"
-version = "2.0.1"
-description = "A lil' TOML parser"
-category = "dev"
+name = "mypy"
+version = "1.4.1"
+description = "Optional static typing for Python"
optional = false
python-versions = ">=3.7"
files = [
- {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
- {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
+ {file = "mypy-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:566e72b0cd6598503e48ea610e0052d1b8168e60a46e0bfd34b3acf2d57f96a8"},
+ {file = "mypy-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ca637024ca67ab24a7fd6f65d280572c3794665eaf5edcc7e90a866544076878"},
+ {file = "mypy-1.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dde1d180cd84f0624c5dcaaa89c89775550a675aff96b5848de78fb11adabcd"},
+ {file = "mypy-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8c4d8e89aa7de683e2056a581ce63c46a0c41e31bd2b6d34144e2c80f5ea53dc"},
+ {file = "mypy-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:bfdca17c36ae01a21274a3c387a63aa1aafe72bff976522886869ef131b937f1"},
+ {file = "mypy-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7549fbf655e5825d787bbc9ecf6028731973f78088fbca3a1f4145c39ef09462"},
+ {file = "mypy-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:98324ec3ecf12296e6422939e54763faedbfcc502ea4a4c38502082711867258"},
+ {file = "mypy-1.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:141dedfdbfe8a04142881ff30ce6e6653c9685b354876b12e4fe6c78598b45e2"},
+ {file = "mypy-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8207b7105829eca6f3d774f64a904190bb2231de91b8b186d21ffd98005f14a7"},
+ {file = "mypy-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:16f0db5b641ba159eff72cff08edc3875f2b62b2fa2bc24f68c1e7a4e8232d01"},
+ {file = "mypy-1.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:470c969bb3f9a9efcedbadcd19a74ffb34a25f8e6b0e02dae7c0e71f8372f97b"},
+ {file = "mypy-1.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5952d2d18b79f7dc25e62e014fe5a23eb1a3d2bc66318df8988a01b1a037c5b"},
+ {file = "mypy-1.4.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:190b6bab0302cec4e9e6767d3eb66085aef2a1cc98fe04936d8a42ed2ba77bb7"},
+ {file = "mypy-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9d40652cc4fe33871ad3338581dca3297ff5f2213d0df345bcfbde5162abf0c9"},
+ {file = "mypy-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:01fd2e9f85622d981fd9063bfaef1aed6e336eaacca00892cd2d82801ab7c042"},
+ {file = "mypy-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2460a58faeea905aeb1b9b36f5065f2dc9a9c6e4c992a6499a2360c6c74ceca3"},
+ {file = "mypy-1.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2746d69a8196698146a3dbe29104f9eb6a2a4d8a27878d92169a6c0b74435b6"},
+ {file = "mypy-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ae704dcfaa180ff7c4cfbad23e74321a2b774f92ca77fd94ce1049175a21c97f"},
+ {file = "mypy-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:43d24f6437925ce50139a310a64b2ab048cb2d3694c84c71c3f2a1626d8101dc"},
+ {file = "mypy-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c482e1246726616088532b5e964e39765b6d1520791348e6c9dc3af25b233828"},
+ {file = "mypy-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:43b592511672017f5b1a483527fd2684347fdffc041c9ef53428c8dc530f79a3"},
+ {file = "mypy-1.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:34a9239d5b3502c17f07fd7c0b2ae6b7dd7d7f6af35fbb5072c6208e76295816"},
+ {file = "mypy-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5703097c4936bbb9e9bce41478c8d08edd2865e177dc4c52be759f81ee4dd26c"},
+ {file = "mypy-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e02d700ec8d9b1859790c0475df4e4092c7bf3272a4fd2c9f33d87fac4427b8f"},
+ {file = "mypy-1.4.1-py3-none-any.whl", hash = "sha256:45d32cec14e7b97af848bddd97d85ea4f0db4d5a149ed9676caa4eb2f7402bb4"},
+ {file = "mypy-1.4.1.tar.gz", hash = "sha256:9bbcd9ab8ea1f2e1c8031c21445b511442cc45c89951e49bbf852cbb70755b1b"},
]
+[package.dependencies]
+mypy-extensions = ">=1.0.0"
+tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
+typing-extensions = ">=4.1.0"
+
+[package.extras]
+dmypy = ["psutil (>=4.0)"]
+install-types = ["pip"]
+python2 = ["typed-ast (>=1.4.0,<2)"]
+reports = ["lxml"]
+
[[package]]
-name = "typing-extensions"
-version = "4.5.0"
-description = "Backported and Experimental Type Hints for Python 3.7+"
-category = "dev"
+name = "mypy-boto3-cloudformation"
+version = "1.28.0"
+description = "Type annotations for boto3.CloudFormation 1.28.0 service generated with mypy-boto3-builder 7.14.5"
optional = false
python-versions = ">=3.7"
files = [
- {file = "typing_extensions-4.5.0-py3-none-any.whl", hash = "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4"},
- {file = "typing_extensions-4.5.0.tar.gz", hash = "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb"},
+ {file = "mypy-boto3-cloudformation-1.28.0.tar.gz", hash = "sha256:0d2ead02c352bc97ae59b65ae8b00d5ce186435b7cf5736213a52f58df192511"},
+ {file = "mypy_boto3_cloudformation-1.28.0-py3-none-any.whl", hash = "sha256:99d5db7d6b220ba016757670a917bdfdab1c475593153833ed6c5cdd9a9aa9ba"},
]
+[package.dependencies]
+typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""}
+
[[package]]
-name = "urllib3"
-version = "1.26.15"
-description = "HTTP library with thread-safe connection pooling, file post, and more."
-category = "main"
+name = "mypy-boto3-lambda"
+version = "1.28.0"
+description = "Type annotations for boto3.Lambda 1.28.0 service generated with mypy-boto3-builder 7.14.5"
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
+python-versions = ">=3.7"
files = [
- {file = "urllib3-1.26.15-py2.py3-none-any.whl", hash = "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"},
- {file = "urllib3-1.26.15.tar.gz", hash = "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305"},
+ {file = "mypy-boto3-lambda-1.28.0.tar.gz", hash = "sha256:a3abaf98e514f2cabed2cf0b1e77c94c81f0fbbba8a549b3c073577a9f9ac196"},
+ {file = "mypy_boto3_lambda-1.28.0-py3-none-any.whl", hash = "sha256:5fd38df6418829b2f3a184918fc8ad1d49b6738509f1832cdc71f33588efbdfb"},
]
-[package.extras]
-brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
-secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
-socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
+[package.dependencies]
+typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.9\""}
+
+[[package]]
+name = "mypy-extensions"
+version = "1.0.0"
+description = "Type system extensions for programs checked with the mypy type checker."
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
+ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
+]
+
+[[package]]
+name = "networkx"
+version = "3.1"
+description = "Python package for creating and manipulating graphs and networks"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "networkx-3.1-py3-none-any.whl", hash = "sha256:4f33f68cb2afcf86f28a45f43efc27a9386b535d567d2127f8f61d51dec58d36"},
+ {file = "networkx-3.1.tar.gz", hash = "sha256:de346335408f84de0eada6ff9fafafff9bcda11f0a0dfaa931133debb146ab61"},
+]
+
+[package.extras]
+default = ["matplotlib (>=3.4)", "numpy (>=1.20)", "pandas (>=1.3)", "scipy (>=1.8)"]
+developer = ["mypy (>=1.1)", "pre-commit (>=3.2)"]
+doc = ["nb2plots (>=0.6)", "numpydoc (>=1.5)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.13)", "sphinx (>=6.1)", "sphinx-gallery (>=0.12)", "texext (>=0.6.7)"]
+extra = ["lxml (>=4.6)", "pydot (>=1.4.2)", "pygraphviz (>=1.10)", "sympy (>=1.10)"]
+test = ["codecov (>=2.1)", "pytest (>=7.2)", "pytest-cov (>=4.0)"]
+
+[[package]]
+name = "openapi-schema-validator"
+version = "0.6.0"
+description = "OpenAPI schema validation for Python"
+optional = false
+python-versions = ">=3.8.0,<4.0.0"
+files = [
+ {file = "openapi_schema_validator-0.6.0-py3-none-any.whl", hash = "sha256:9e95b95b621efec5936245025df0d6a7ffacd1551e91d09196b3053040c931d7"},
+ {file = "openapi_schema_validator-0.6.0.tar.gz", hash = "sha256:921b7c1144b856ca3813e41ecff98a4050f7611824dfc5c6ead7072636af0520"},
+]
+
+[package.dependencies]
+jsonschema = ">=4.18.0,<5.0.0"
+jsonschema-specifications = ">=2023.5.2,<2024.0.0"
+rfc3339-validator = "*"
+
+[[package]]
+name = "openapi-spec-validator"
+version = "0.6.0"
+description = "OpenAPI 2.0 (aka Swagger) and OpenAPI 3 spec validator"
+optional = false
+python-versions = ">=3.8.0,<4.0.0"
+files = [
+ {file = "openapi_spec_validator-0.6.0-py3-none-any.whl", hash = "sha256:675f1a3c0d0d8eff9116694acde88bcd4613a95bf5240270724d9d78c78f26d6"},
+ {file = "openapi_spec_validator-0.6.0.tar.gz", hash = "sha256:68c4c212c88ef14c6b1a591b895bf742c455783c7ebba2507abd7dbc1365a616"},
+]
+
+[package.dependencies]
+importlib-resources = {version = ">=5.8.0,<6.0.0", markers = "python_version < \"3.9\""}
+jsonschema = ">=4.18.0,<5.0.0"
+jsonschema-spec = ">=0.2.3,<0.3.0"
+lazy-object-proxy = ">=1.7.1,<2.0.0"
+openapi-schema-validator = ">=0.6.0,<0.7.0"
+
+[[package]]
+name = "packaging"
+version = "23.1"
+description = "Core utilities for Python packages"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"},
+ {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"},
+]
+
+[[package]]
+name = "pathable"
+version = "0.4.3"
+description = "Object-oriented paths"
+optional = false
+python-versions = ">=3.7.0,<4.0.0"
+files = [
+ {file = "pathable-0.4.3-py3-none-any.whl", hash = "sha256:cdd7b1f9d7d5c8b8d3315dbf5a86b2596053ae845f056f57d97c0eefff84da14"},
+ {file = "pathable-0.4.3.tar.gz", hash = "sha256:5c869d315be50776cc8a993f3af43e0c60dc01506b399643f919034ebf4cdcab"},
+]
+
+[[package]]
+name = "pathspec"
+version = "0.11.1"
+description = "Utility library for gitignore style pattern matching of file paths."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"},
+ {file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"},
+]
+
+[[package]]
+name = "pbr"
+version = "5.11.1"
+description = "Python Build Reasonableness"
+optional = false
+python-versions = ">=2.6"
+files = [
+ {file = "pbr-5.11.1-py2.py3-none-any.whl", hash = "sha256:567f09558bae2b3ab53cb3c1e2e33e726ff3338e7bae3db5dc954b3a44eef12b"},
+ {file = "pbr-5.11.1.tar.gz", hash = "sha256:aefc51675b0b533d56bb5fd1c8c6c0522fe31896679882e1c4c63d5e4a0fccb3"},
+]
+
+[[package]]
+name = "pkgutil-resolve-name"
+version = "1.3.10"
+description = "Resolve a name to an object."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "pkgutil_resolve_name-1.3.10-py3-none-any.whl", hash = "sha256:ca27cc078d25c5ad71a9de0a7a330146c4e014c2462d9af19c6b828280649c5e"},
+ {file = "pkgutil_resolve_name-1.3.10.tar.gz", hash = "sha256:357d6c9e6a755653cfd78893817c0853af365dd51ec97f3d358a819373bbd174"},
+]
+
+[[package]]
+name = "platformdirs"
+version = "3.8.1"
+description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "platformdirs-3.8.1-py3-none-any.whl", hash = "sha256:cec7b889196b9144d088e4c57d9ceef7374f6c39694ad1577a0aab50d27ea28c"},
+ {file = "platformdirs-3.8.1.tar.gz", hash = "sha256:f87ca4fcff7d2b0f81c6a748a77973d7af0f4d526f98f308477c3c436c74d528"},
+]
+
+[package.extras]
+docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
+test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)"]
+
+[[package]]
+name = "pluggy"
+version = "1.2.0"
+description = "plugin and hook calling mechanisms for python"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849"},
+ {file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"},
+]
+
+[package.extras]
+dev = ["pre-commit", "tox"]
+testing = ["pytest", "pytest-benchmark"]
+
+[[package]]
+name = "py-partiql-parser"
+version = "0.3.3"
+description = "Pure Python PartiQL Parser"
+optional = false
+python-versions = "*"
+files = [
+ {file = "py-partiql-parser-0.3.3.tar.gz", hash = "sha256:351672721dfaaa00bbd82c4a3340d5d2defb589d2dd5baaecf6e493910f1c033"},
+ {file = "py_partiql_parser-0.3.3-py3-none-any.whl", hash = "sha256:cd4a53af362bb589968b17b321d1ac46d06d21d333247e0e6f79b11db2d0306f"},
+]
+
+[package.extras]
+dev = ["black (==22.6.0)", "flake8", "mypy (==0.971)", "pytest", "sure (==2.0.0)"]
+
+[[package]]
+name = "pyasn1"
+version = "0.5.0"
+description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)"
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
+files = [
+ {file = "pyasn1-0.5.0-py2.py3-none-any.whl", hash = "sha256:87a2121042a1ac9358cabcaf1d07680ff97ee6404333bacca15f76aa8ad01a57"},
+ {file = "pyasn1-0.5.0.tar.gz", hash = "sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde"},
+]
+
+[[package]]
+name = "pycodestyle"
+version = "2.10.0"
+description = "Python style guide checker"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "pycodestyle-2.10.0-py2.py3-none-any.whl", hash = "sha256:8a4eaf0d0495c7395bdab3589ac2db602797d76207242c17d470186815706610"},
+ {file = "pycodestyle-2.10.0.tar.gz", hash = "sha256:347187bdb476329d98f695c213d7295a846d1152ff4fe9bacb8a9590b8ee7053"},
+]
+
+[[package]]
+name = "pycparser"
+version = "2.21"
+description = "C parser in Python"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+files = [
+ {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"},
+ {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
+]
+
+[[package]]
+name = "pydantic"
+version = "1.10.11"
+description = "Data validation and settings management using python type hints"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pydantic-1.10.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ff44c5e89315b15ff1f7fdaf9853770b810936d6b01a7bcecaa227d2f8fe444f"},
+ {file = "pydantic-1.10.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a6c098d4ab5e2d5b3984d3cb2527e2d6099d3de85630c8934efcfdc348a9760e"},
+ {file = "pydantic-1.10.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16928fdc9cb273c6af00d9d5045434c39afba5f42325fb990add2c241402d151"},
+ {file = "pydantic-1.10.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0588788a9a85f3e5e9ebca14211a496409cb3deca5b6971ff37c556d581854e7"},
+ {file = "pydantic-1.10.11-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e9baf78b31da2dc3d3f346ef18e58ec5f12f5aaa17ac517e2ffd026a92a87588"},
+ {file = "pydantic-1.10.11-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:373c0840f5c2b5b1ccadd9286782852b901055998136287828731868027a724f"},
+ {file = "pydantic-1.10.11-cp310-cp310-win_amd64.whl", hash = "sha256:c3339a46bbe6013ef7bdd2844679bfe500347ac5742cd4019a88312aa58a9847"},
+ {file = "pydantic-1.10.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:08a6c32e1c3809fbc49debb96bf833164f3438b3696abf0fbeceb417d123e6eb"},
+ {file = "pydantic-1.10.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a451ccab49971af043ec4e0d207cbc8cbe53dbf148ef9f19599024076fe9c25b"},
+ {file = "pydantic-1.10.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b02d24f7b2b365fed586ed73582c20f353a4c50e4be9ba2c57ab96f8091ddae"},
+ {file = "pydantic-1.10.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f34739a89260dfa420aa3cbd069fbcc794b25bbe5c0a214f8fb29e363484b66"},
+ {file = "pydantic-1.10.11-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e297897eb4bebde985f72a46a7552a7556a3dd11e7f76acda0c1093e3dbcf216"},
+ {file = "pydantic-1.10.11-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d185819a7a059550ecb85d5134e7d40f2565f3dd94cfd870132c5f91a89cf58c"},
+ {file = "pydantic-1.10.11-cp311-cp311-win_amd64.whl", hash = "sha256:4400015f15c9b464c9db2d5d951b6a780102cfa5870f2c036d37c23b56f7fc1b"},
+ {file = "pydantic-1.10.11-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2417de68290434461a266271fc57274a138510dca19982336639484c73a07af6"},
+ {file = "pydantic-1.10.11-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:331c031ba1554b974c98679bd0780d89670d6fd6f53f5d70b10bdc9addee1713"},
+ {file = "pydantic-1.10.11-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8268a735a14c308923e8958363e3a3404f6834bb98c11f5ab43251a4e410170c"},
+ {file = "pydantic-1.10.11-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:44e51ba599c3ef227e168424e220cd3e544288c57829520dc90ea9cb190c3248"},
+ {file = "pydantic-1.10.11-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d7781f1d13b19700b7949c5a639c764a077cbbdd4322ed505b449d3ca8edcb36"},
+ {file = "pydantic-1.10.11-cp37-cp37m-win_amd64.whl", hash = "sha256:7522a7666157aa22b812ce14c827574ddccc94f361237ca6ea8bb0d5c38f1629"},
+ {file = "pydantic-1.10.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc64eab9b19cd794a380179ac0e6752335e9555d214cfcb755820333c0784cb3"},
+ {file = "pydantic-1.10.11-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8dc77064471780262b6a68fe67e013298d130414d5aaf9b562c33987dbd2cf4f"},
+ {file = "pydantic-1.10.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe429898f2c9dd209bd0632a606bddc06f8bce081bbd03d1c775a45886e2c1cb"},
+ {file = "pydantic-1.10.11-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:192c608ad002a748e4a0bed2ddbcd98f9b56df50a7c24d9a931a8c5dd053bd3d"},
+ {file = "pydantic-1.10.11-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ef55392ec4bb5721f4ded1096241e4b7151ba6d50a50a80a2526c854f42e6a2f"},
+ {file = "pydantic-1.10.11-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:41e0bb6efe86281623abbeeb0be64eab740c865388ee934cd3e6a358784aca6e"},
+ {file = "pydantic-1.10.11-cp38-cp38-win_amd64.whl", hash = "sha256:265a60da42f9f27e0b1014eab8acd3e53bd0bad5c5b4884e98a55f8f596b2c19"},
+ {file = "pydantic-1.10.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:469adf96c8e2c2bbfa655fc7735a2a82f4c543d9fee97bd113a7fb509bf5e622"},
+ {file = "pydantic-1.10.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e6cbfbd010b14c8a905a7b10f9fe090068d1744d46f9e0c021db28daeb8b6de1"},
+ {file = "pydantic-1.10.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abade85268cc92dff86d6effcd917893130f0ff516f3d637f50dadc22ae93999"},
+ {file = "pydantic-1.10.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e9738b0f2e6c70f44ee0de53f2089d6002b10c33264abee07bdb5c7f03038303"},
+ {file = "pydantic-1.10.11-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:787cf23e5a0cde753f2eabac1b2e73ae3844eb873fd1f5bdbff3048d8dbb7604"},
+ {file = "pydantic-1.10.11-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:174899023337b9fc685ac8adaa7b047050616136ccd30e9070627c1aaab53a13"},
+ {file = "pydantic-1.10.11-cp39-cp39-win_amd64.whl", hash = "sha256:1954f8778489a04b245a1e7b8b22a9d3ea8ef49337285693cf6959e4b757535e"},
+ {file = "pydantic-1.10.11-py3-none-any.whl", hash = "sha256:008c5e266c8aada206d0627a011504e14268a62091450210eda7c07fabe6963e"},
+ {file = "pydantic-1.10.11.tar.gz", hash = "sha256:f66d479cf7eb331372c470614be6511eae96f1f120344c25f3f9bb59fb1b5528"},
+]
+
+[package.dependencies]
+typing-extensions = ">=4.2.0"
+
+[package.extras]
+dotenv = ["python-dotenv (>=0.10.4)"]
+email = ["email-validator (>=1.0.3)"]
+
+[[package]]
+name = "pyflakes"
+version = "3.0.1"
+description = "passive checker of Python programs"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "pyflakes-3.0.1-py2.py3-none-any.whl", hash = "sha256:ec55bf7fe21fff7f1ad2f7da62363d749e2a470500eab1b555334b67aa1ef8cf"},
+ {file = "pyflakes-3.0.1.tar.gz", hash = "sha256:ec8b276a6b60bd80defed25add7e439881c19e64850afd9b346283d4165fd0fd"},
+]
+
+[[package]]
+name = "pyparsing"
+version = "3.1.0"
+description = "pyparsing module - Classes and methods to define and execute parsing grammars"
+optional = false
+python-versions = ">=3.6.8"
+files = [
+ {file = "pyparsing-3.1.0-py3-none-any.whl", hash = "sha256:d554a96d1a7d3ddaf7183104485bc19fd80543ad6ac5bdb6426719d766fb06c1"},
+ {file = "pyparsing-3.1.0.tar.gz", hash = "sha256:edb662d6fe322d6e990b1594b5feaeadf806803359e3d4d42f11e295e588f0ea"},
+]
+
+[package.extras]
+diagrams = ["jinja2", "railroad-diagrams"]
+
+[[package]]
+name = "pytest"
+version = "7.4.0"
+description = "pytest: simple powerful testing with Python"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pytest-7.4.0-py3-none-any.whl", hash = "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32"},
+ {file = "pytest-7.4.0.tar.gz", hash = "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
+iniconfig = "*"
+packaging = "*"
+pluggy = ">=0.12,<2.0"
+tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
+
+[package.extras]
+testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
+
+[[package]]
+name = "pytest-cov"
+version = "4.1.0"
+description = "Pytest plugin for measuring coverage."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"},
+ {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"},
+]
+
+[package.dependencies]
+coverage = {version = ">=5.2.1", extras = ["toml"]}
+pytest = ">=4.6"
+
+[package.extras]
+testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"]
+
+[[package]]
+name = "python-dateutil"
+version = "2.8.2"
+description = "Extensions to the standard Python datetime module"
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
+files = [
+ {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
+ {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
+]
+
+[package.dependencies]
+six = ">=1.5"
+
+[[package]]
+name = "python-jose"
+version = "3.3.0"
+description = "JOSE implementation in Python"
+optional = false
+python-versions = "*"
+files = [
+ {file = "python-jose-3.3.0.tar.gz", hash = "sha256:55779b5e6ad599c6336191246e95eb2293a9ddebd555f796a65f838f07e5d78a"},
+ {file = "python_jose-3.3.0-py2.py3-none-any.whl", hash = "sha256:9b1376b023f8b298536eedd47ae1089bcdb848f1535ab30555cd92002d78923a"},
+]
+
+[package.dependencies]
+cryptography = {version = ">=3.4.0", optional = true, markers = "extra == \"cryptography\""}
+ecdsa = "!=0.15"
+pyasn1 = "*"
+rsa = "*"
+
+[package.extras]
+cryptography = ["cryptography (>=3.4.0)"]
+pycrypto = ["pyasn1", "pycrypto (>=2.6.0,<2.7.0)"]
+pycryptodome = ["pyasn1", "pycryptodome (>=3.3.1,<4.0.0)"]
+
+[[package]]
+name = "pywin32"
+version = "306"
+description = "Python for Window Extensions"
+optional = false
+python-versions = "*"
+files = [
+ {file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"},
+ {file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"},
+ {file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"},
+ {file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"},
+ {file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"},
+ {file = "pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b"},
+ {file = "pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e"},
+ {file = "pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040"},
+ {file = "pywin32-306-cp37-cp37m-win32.whl", hash = "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65"},
+ {file = "pywin32-306-cp37-cp37m-win_amd64.whl", hash = "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36"},
+ {file = "pywin32-306-cp38-cp38-win32.whl", hash = "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a"},
+ {file = "pywin32-306-cp38-cp38-win_amd64.whl", hash = "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0"},
+ {file = "pywin32-306-cp39-cp39-win32.whl", hash = "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802"},
+ {file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"},
+]
+
+[[package]]
+name = "pyyaml"
+version = "6.0"
+description = "YAML parser and emitter for Python"
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
+ {file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"},
+ {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"},
+ {file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"},
+ {file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"},
+ {file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"},
+ {file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"},
+ {file = "PyYAML-6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358"},
+ {file = "PyYAML-6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1"},
+ {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d"},
+ {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f"},
+ {file = "PyYAML-6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782"},
+ {file = "PyYAML-6.0-cp311-cp311-win32.whl", hash = "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7"},
+ {file = "PyYAML-6.0-cp311-cp311-win_amd64.whl", hash = "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf"},
+ {file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"},
+ {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"},
+ {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"},
+ {file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"},
+ {file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"},
+ {file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"},
+ {file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"},
+ {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"},
+ {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"},
+ {file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"},
+ {file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"},
+ {file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"},
+ {file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"},
+ {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"},
+ {file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"},
+ {file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"},
+ {file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"},
+ {file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"},
+ {file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"},
+ {file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"},
+ {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"},
+ {file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"},
+ {file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"},
+ {file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"},
+ {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"},
+ {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"},
+]
+
+[[package]]
+name = "referencing"
+version = "0.29.1"
+description = "JSON Referencing + Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "referencing-0.29.1-py3-none-any.whl", hash = "sha256:d3c8f323ee1480095da44d55917cfb8278d73d6b4d5f677e3e40eb21314ac67f"},
+ {file = "referencing-0.29.1.tar.gz", hash = "sha256:90cb53782d550ba28d2166ef3f55731f38397def8832baac5d45235f1995e35e"},
+]
+
+[package.dependencies]
+attrs = ">=22.2.0"
+rpds-py = ">=0.7.0"
+
+[[package]]
+name = "regex"
+version = "2023.6.3"
+description = "Alternative regular expression module, to replace re."
+optional = false
+python-versions = ">=3.6"
+files = [
+ {file = "regex-2023.6.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:824bf3ac11001849aec3fa1d69abcb67aac3e150a933963fb12bda5151fe1bfd"},
+ {file = "regex-2023.6.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:05ed27acdf4465c95826962528f9e8d41dbf9b1aa8531a387dee6ed215a3e9ef"},
+ {file = "regex-2023.6.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b49c764f88a79160fa64f9a7b425620e87c9f46095ef9c9920542ab2495c8bc"},
+ {file = "regex-2023.6.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8e3f1316c2293e5469f8f09dc2d76efb6c3982d3da91ba95061a7e69489a14ef"},
+ {file = "regex-2023.6.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:43e1dd9d12df9004246bacb79a0e5886b3b6071b32e41f83b0acbf293f820ee8"},
+ {file = "regex-2023.6.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4959e8bcbfda5146477d21c3a8ad81b185cd252f3d0d6e4724a5ef11c012fb06"},
+ {file = "regex-2023.6.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:af4dd387354dc83a3bff67127a124c21116feb0d2ef536805c454721c5d7993d"},
+ {file = "regex-2023.6.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2239d95d8e243658b8dbb36b12bd10c33ad6e6933a54d36ff053713f129aa536"},
+ {file = "regex-2023.6.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:890e5a11c97cf0d0c550eb661b937a1e45431ffa79803b942a057c4fb12a2da2"},
+ {file = "regex-2023.6.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a8105e9af3b029f243ab11ad47c19b566482c150c754e4c717900a798806b222"},
+ {file = "regex-2023.6.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:25be746a8ec7bc7b082783216de8e9473803706723b3f6bef34b3d0ed03d57e2"},
+ {file = "regex-2023.6.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:3676f1dd082be28b1266c93f618ee07741b704ab7b68501a173ce7d8d0d0ca18"},
+ {file = "regex-2023.6.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:10cb847aeb1728412c666ab2e2000ba6f174f25b2bdc7292e7dd71b16db07568"},
+ {file = "regex-2023.6.3-cp310-cp310-win32.whl", hash = "sha256:dbbbfce33cd98f97f6bffb17801b0576e653f4fdb1d399b2ea89638bc8d08ae1"},
+ {file = "regex-2023.6.3-cp310-cp310-win_amd64.whl", hash = "sha256:c5f8037000eb21e4823aa485149f2299eb589f8d1fe4b448036d230c3f4e68e0"},
+ {file = "regex-2023.6.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c123f662be8ec5ab4ea72ea300359023a5d1df095b7ead76fedcd8babbedf969"},
+ {file = "regex-2023.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9edcbad1f8a407e450fbac88d89e04e0b99a08473f666a3f3de0fd292badb6aa"},
+ {file = "regex-2023.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcba6dae7de533c876255317c11f3abe4907ba7d9aa15d13e3d9710d4315ec0e"},
+ {file = "regex-2023.6.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:29cdd471ebf9e0f2fb3cac165efedc3c58db841d83a518b082077e612d3ee5df"},
+ {file = "regex-2023.6.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:12b74fbbf6cbbf9dbce20eb9b5879469e97aeeaa874145517563cca4029db65c"},
+ {file = "regex-2023.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c29ca1bd61b16b67be247be87390ef1d1ef702800f91fbd1991f5c4421ebae8"},
+ {file = "regex-2023.6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d77f09bc4b55d4bf7cc5eba785d87001d6757b7c9eec237fe2af57aba1a071d9"},
+ {file = "regex-2023.6.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ea353ecb6ab5f7e7d2f4372b1e779796ebd7b37352d290096978fea83c4dba0c"},
+ {file = "regex-2023.6.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:10590510780b7541969287512d1b43f19f965c2ece6c9b1c00fc367b29d8dce7"},
+ {file = "regex-2023.6.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e2fbd6236aae3b7f9d514312cdb58e6494ee1c76a9948adde6eba33eb1c4264f"},
+ {file = "regex-2023.6.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:6b2675068c8b56f6bfd5a2bda55b8accbb96c02fd563704732fd1c95e2083461"},
+ {file = "regex-2023.6.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74419d2b50ecb98360cfaa2974da8689cb3b45b9deff0dcf489c0d333bcc1477"},
+ {file = "regex-2023.6.3-cp311-cp311-win32.whl", hash = "sha256:fb5ec16523dc573a4b277663a2b5a364e2099902d3944c9419a40ebd56a118f9"},
+ {file = "regex-2023.6.3-cp311-cp311-win_amd64.whl", hash = "sha256:09e4a1a6acc39294a36b7338819b10baceb227f7f7dbbea0506d419b5a1dd8af"},
+ {file = "regex-2023.6.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:0654bca0cdf28a5956c83839162692725159f4cda8d63e0911a2c0dc76166525"},
+ {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:463b6a3ceb5ca952e66550a4532cef94c9a0c80dc156c4cc343041951aec1697"},
+ {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:87b2a5bb5e78ee0ad1de71c664d6eb536dc3947a46a69182a90f4410f5e3f7dd"},
+ {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6343c6928282c1f6a9db41f5fd551662310e8774c0e5ebccb767002fcf663ca9"},
+ {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6192d5af2ccd2a38877bfef086d35e6659566a335b1492786ff254c168b1693"},
+ {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:74390d18c75054947e4194019077e243c06fbb62e541d8817a0fa822ea310c14"},
+ {file = "regex-2023.6.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:742e19a90d9bb2f4a6cf2862b8b06dea5e09b96c9f2df1779e53432d7275331f"},
+ {file = "regex-2023.6.3-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:8abbc5d54ea0ee80e37fef009e3cec5dafd722ed3c829126253d3e22f3846f1e"},
+ {file = "regex-2023.6.3-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:c2b867c17a7a7ae44c43ebbeb1b5ff406b3e8d5b3e14662683e5e66e6cc868d3"},
+ {file = "regex-2023.6.3-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:d831c2f8ff278179705ca59f7e8524069c1a989e716a1874d6d1aab6119d91d1"},
+ {file = "regex-2023.6.3-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:ee2d1a9a253b1729bb2de27d41f696ae893507c7db224436abe83ee25356f5c1"},
+ {file = "regex-2023.6.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:61474f0b41fe1a80e8dfa70f70ea1e047387b7cd01c85ec88fa44f5d7561d787"},
+ {file = "regex-2023.6.3-cp36-cp36m-win32.whl", hash = "sha256:0b71e63226e393b534105fcbdd8740410dc6b0854c2bfa39bbda6b0d40e59a54"},
+ {file = "regex-2023.6.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bbb02fd4462f37060122e5acacec78e49c0fbb303c30dd49c7f493cf21fc5b27"},
+ {file = "regex-2023.6.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b862c2b9d5ae38a68b92e215b93f98d4c5e9454fa36aae4450f61dd33ff48487"},
+ {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:976d7a304b59ede34ca2921305b57356694f9e6879db323fd90a80f865d355a3"},
+ {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:83320a09188e0e6c39088355d423aa9d056ad57a0b6c6381b300ec1a04ec3d16"},
+ {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9427a399501818a7564f8c90eced1e9e20709ece36be701f394ada99890ea4b3"},
+ {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7178bbc1b2ec40eaca599d13c092079bf529679bf0371c602edaa555e10b41c3"},
+ {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:837328d14cde912af625d5f303ec29f7e28cdab588674897baafaf505341f2fc"},
+ {file = "regex-2023.6.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2d44dc13229905ae96dd2ae2dd7cebf824ee92bc52e8cf03dcead37d926da019"},
+ {file = "regex-2023.6.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d54af539295392611e7efbe94e827311eb8b29668e2b3f4cadcfe6f46df9c777"},
+ {file = "regex-2023.6.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7117d10690c38a622e54c432dfbbd3cbd92f09401d622902c32f6d377e2300ee"},
+ {file = "regex-2023.6.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bb60b503ec8a6e4e3e03a681072fa3a5adcbfa5479fa2d898ae2b4a8e24c4591"},
+ {file = "regex-2023.6.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:65ba8603753cec91c71de423a943ba506363b0e5c3fdb913ef8f9caa14b2c7e0"},
+ {file = "regex-2023.6.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:271f0bdba3c70b58e6f500b205d10a36fb4b58bd06ac61381b68de66442efddb"},
+ {file = "regex-2023.6.3-cp37-cp37m-win32.whl", hash = "sha256:9beb322958aaca059f34975b0df135181f2e5d7a13b84d3e0e45434749cb20f7"},
+ {file = "regex-2023.6.3-cp37-cp37m-win_amd64.whl", hash = "sha256:fea75c3710d4f31389eed3c02f62d0b66a9da282521075061ce875eb5300cf23"},
+ {file = "regex-2023.6.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8f56fcb7ff7bf7404becdfc60b1e81a6d0561807051fd2f1860b0d0348156a07"},
+ {file = "regex-2023.6.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d2da3abc88711bce7557412310dfa50327d5769a31d1c894b58eb256459dc289"},
+ {file = "regex-2023.6.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a99b50300df5add73d307cf66abea093304a07eb017bce94f01e795090dea87c"},
+ {file = "regex-2023.6.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5708089ed5b40a7b2dc561e0c8baa9535b77771b64a8330b684823cfd5116036"},
+ {file = "regex-2023.6.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:687ea9d78a4b1cf82f8479cab23678aff723108df3edeac098e5b2498879f4a7"},
+ {file = "regex-2023.6.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d3850beab9f527f06ccc94b446c864059c57651b3f911fddb8d9d3ec1d1b25d"},
+ {file = "regex-2023.6.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e8915cc96abeb8983cea1df3c939e3c6e1ac778340c17732eb63bb96247b91d2"},
+ {file = "regex-2023.6.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:841d6e0e5663d4c7b4c8099c9997be748677d46cbf43f9f471150e560791f7ff"},
+ {file = "regex-2023.6.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9edce5281f965cf135e19840f4d93d55b3835122aa76ccacfd389e880ba4cf82"},
+ {file = "regex-2023.6.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b956231ebdc45f5b7a2e1f90f66a12be9610ce775fe1b1d50414aac1e9206c06"},
+ {file = "regex-2023.6.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:36efeba71c6539d23c4643be88295ce8c82c88bbd7c65e8a24081d2ca123da3f"},
+ {file = "regex-2023.6.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:cf67ca618b4fd34aee78740bea954d7c69fdda419eb208c2c0c7060bb822d747"},
+ {file = "regex-2023.6.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b4598b1897837067a57b08147a68ac026c1e73b31ef6e36deeeb1fa60b2933c9"},
+ {file = "regex-2023.6.3-cp38-cp38-win32.whl", hash = "sha256:f415f802fbcafed5dcc694c13b1292f07fe0befdb94aa8a52905bd115ff41e88"},
+ {file = "regex-2023.6.3-cp38-cp38-win_amd64.whl", hash = "sha256:d4f03bb71d482f979bda92e1427f3ec9b220e62a7dd337af0aa6b47bf4498f72"},
+ {file = "regex-2023.6.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ccf91346b7bd20c790310c4147eee6ed495a54ddb6737162a36ce9dbef3e4751"},
+ {file = "regex-2023.6.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b28f5024a3a041009eb4c333863d7894d191215b39576535c6734cd88b0fcb68"},
+ {file = "regex-2023.6.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0bb18053dfcfed432cc3ac632b5e5e5c5b7e55fb3f8090e867bfd9b054dbcbf"},
+ {file = "regex-2023.6.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a5bfb3004f2144a084a16ce19ca56b8ac46e6fd0651f54269fc9e230edb5e4a"},
+ {file = "regex-2023.6.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c6b48d0fa50d8f4df3daf451be7f9689c2bde1a52b1225c5926e3f54b6a9ed1"},
+ {file = "regex-2023.6.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:051da80e6eeb6e239e394ae60704d2b566aa6a7aed6f2890a7967307267a5dc6"},
+ {file = "regex-2023.6.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a4c3b7fa4cdaa69268748665a1a6ff70c014d39bb69c50fda64b396c9116cf77"},
+ {file = "regex-2023.6.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:457b6cce21bee41ac292d6753d5e94dcbc5c9e3e3a834da285b0bde7aa4a11e9"},
+ {file = "regex-2023.6.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:aad51907d74fc183033ad796dd4c2e080d1adcc4fd3c0fd4fd499f30c03011cd"},
+ {file = "regex-2023.6.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0385e73da22363778ef2324950e08b689abdf0b108a7d8decb403ad7f5191938"},
+ {file = "regex-2023.6.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c6a57b742133830eec44d9b2290daf5cbe0a2f1d6acee1b3c7b1c7b2f3606df7"},
+ {file = "regex-2023.6.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:3e5219bf9e75993d73ab3d25985c857c77e614525fac9ae02b1bebd92f7cecac"},
+ {file = "regex-2023.6.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e5087a3c59eef624a4591ef9eaa6e9a8d8a94c779dade95d27c0bc24650261cd"},
+ {file = "regex-2023.6.3-cp39-cp39-win32.whl", hash = "sha256:20326216cc2afe69b6e98528160b225d72f85ab080cbdf0b11528cbbaba2248f"},
+ {file = "regex-2023.6.3-cp39-cp39-win_amd64.whl", hash = "sha256:bdff5eab10e59cf26bc479f565e25ed71a7d041d1ded04ccf9aee1d9f208487a"},
+ {file = "regex-2023.6.3.tar.gz", hash = "sha256:72d1a25bf36d2050ceb35b517afe13864865268dfb45910e2e17a84be6cbfeb0"},
+]
+
+[[package]]
+name = "requests"
+version = "2.31.0"
+description = "Python HTTP for Humans."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"},
+ {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"},
+]
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+charset-normalizer = ">=2,<4"
+idna = ">=2.5,<4"
+urllib3 = ">=1.21.1,<3"
+
+[package.extras]
+socks = ["PySocks (>=1.5.6,!=1.5.7)"]
+use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
+
+[[package]]
+name = "responses"
+version = "0.23.1"
+description = "A utility library for mocking out the `requests` Python library."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "responses-0.23.1-py3-none-any.whl", hash = "sha256:8a3a5915713483bf353b6f4079ba8b2a29029d1d1090a503c70b0dc5d9d0c7bd"},
+ {file = "responses-0.23.1.tar.gz", hash = "sha256:c4d9aa9fc888188f0c673eff79a8dadbe2e75b7fe879dc80a221a06e0a68138f"},
+]
+
+[package.dependencies]
+pyyaml = "*"
+requests = ">=2.22.0,<3.0"
+types-PyYAML = "*"
+urllib3 = ">=1.25.10"
+
+[package.extras]
+tests = ["coverage (>=6.0.0)", "flake8", "mypy", "pytest (>=7.0.0)", "pytest-asyncio", "pytest-cov", "pytest-httpserver", "tomli", "tomli-w", "types-requests"]
+
+[[package]]
+name = "rfc3339-validator"
+version = "0.1.4"
+description = "A pure python RFC3339 validator"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+files = [
+ {file = "rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa"},
+ {file = "rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b"},
+]
+
+[package.dependencies]
+six = "*"
+
+[[package]]
+name = "rpds-py"
+version = "0.8.10"
+description = "Python bindings to Rust's persistent data structures (rpds)"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "rpds_py-0.8.10-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:93d06cccae15b3836247319eee7b6f1fdcd6c10dabb4e6d350d27bd0bdca2711"},
+ {file = "rpds_py-0.8.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3816a890a6a9e9f1de250afa12ca71c9a7a62f2b715a29af6aaee3aea112c181"},
+ {file = "rpds_py-0.8.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7c6304b894546b5a6bdc0fe15761fa53fe87d28527a7142dae8de3c663853e1"},
+ {file = "rpds_py-0.8.10-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ad3bfb44c8840fb4be719dc58e229f435e227fbfbe133dc33f34981ff622a8f8"},
+ {file = "rpds_py-0.8.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:14f1c356712f66653b777ecd8819804781b23dbbac4eade4366b94944c9e78ad"},
+ {file = "rpds_py-0.8.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:82bb361cae4d0a627006dadd69dc2f36b7ad5dc1367af9d02e296ec565248b5b"},
+ {file = "rpds_py-0.8.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2e3c4f2a8e3da47f850d7ea0d7d56720f0f091d66add889056098c4b2fd576c"},
+ {file = "rpds_py-0.8.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:15a90d0ac11b4499171067ae40a220d1ca3cb685ec0acc356d8f3800e07e4cb8"},
+ {file = "rpds_py-0.8.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:70bb9c8004b97b4ef7ae56a2aa56dfaa74734a0987c78e7e85f00004ab9bf2d0"},
+ {file = "rpds_py-0.8.10-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:d64f9f88d5203274a002b54442cafc9c7a1abff2a238f3e767b70aadf919b451"},
+ {file = "rpds_py-0.8.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ccbbd276642788c4376fbe8d4e6c50f0fb4972ce09ecb051509062915891cbf0"},
+ {file = "rpds_py-0.8.10-cp310-none-win32.whl", hash = "sha256:fafc0049add8043ad07ab5382ee80d80ed7e3699847f26c9a5cf4d3714d96a84"},
+ {file = "rpds_py-0.8.10-cp310-none-win_amd64.whl", hash = "sha256:915031002c86a5add7c6fd4beb601b2415e8a1c956590a5f91d825858e92fe6e"},
+ {file = "rpds_py-0.8.10-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:84eb541a44f7a18f07a6bfc48b95240739e93defe1fdfb4f2a295f37837945d7"},
+ {file = "rpds_py-0.8.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f59996d0550894affaad8743e97b9b9c98f638b221fac12909210ec3d9294786"},
+ {file = "rpds_py-0.8.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9adb5664b78fcfcd830000416c8cc69853ef43cb084d645b3f1f0296edd9bae"},
+ {file = "rpds_py-0.8.10-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f96f3f98fbff7af29e9edf9a6584f3c1382e7788783d07ba3721790625caa43e"},
+ {file = "rpds_py-0.8.10-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:376b8de737401050bd12810003d207e824380be58810c031f10ec563ff6aef3d"},
+ {file = "rpds_py-0.8.10-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d1c2bc319428d50b3e0fa6b673ab8cc7fa2755a92898db3a594cbc4eeb6d1f7"},
+ {file = "rpds_py-0.8.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:73a1e48430f418f0ac3dfd87860e4cc0d33ad6c0f589099a298cb53724db1169"},
+ {file = "rpds_py-0.8.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:134ec8f14ca7dbc6d9ae34dac632cdd60939fe3734b5d287a69683c037c51acb"},
+ {file = "rpds_py-0.8.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4b519bac7c09444dd85280fd60f28c6dde4389c88dddf4279ba9b630aca3bbbe"},
+ {file = "rpds_py-0.8.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9cd57981d9fab04fc74438d82460f057a2419974d69a96b06a440822d693b3c0"},
+ {file = "rpds_py-0.8.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:69d089c026f6a8b9d64a06ff67dc3be196707b699d7f6ca930c25f00cf5e30d8"},
+ {file = "rpds_py-0.8.10-cp311-none-win32.whl", hash = "sha256:220bdcad2d2936f674650d304e20ac480a3ce88a40fe56cd084b5780f1d104d9"},
+ {file = "rpds_py-0.8.10-cp311-none-win_amd64.whl", hash = "sha256:6c6a0225b8501d881b32ebf3f5807a08ad3685b5eb5f0a6bfffd3a6e039b2055"},
+ {file = "rpds_py-0.8.10-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:e3d0cd3dff0e7638a7b5390f3a53057c4e347f4ef122ee84ed93fc2fb7ea4aa2"},
+ {file = "rpds_py-0.8.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d77dff3a5aa5eedcc3da0ebd10ff8e4969bc9541aa3333a8d41715b429e99f47"},
+ {file = "rpds_py-0.8.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41c89a366eae49ad9e65ed443a8f94aee762931a1e3723749d72aeac80f5ef2f"},
+ {file = "rpds_py-0.8.10-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3793c21494bad1373da517001d0849eea322e9a049a0e4789e50d8d1329df8e7"},
+ {file = "rpds_py-0.8.10-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:805a5f3f05d186c5d50de2e26f765ba7896d0cc1ac5b14ffc36fae36df5d2f10"},
+ {file = "rpds_py-0.8.10-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b01b39ad5411563031ea3977bbbc7324d82b088e802339e6296f082f78f6115c"},
+ {file = "rpds_py-0.8.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3f1e860be21f3e83011116a65e7310486300e08d9a3028e73e8d13bb6c77292"},
+ {file = "rpds_py-0.8.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a13c8e56c46474cd5958d525ce6a9996727a83d9335684e41f5192c83deb6c58"},
+ {file = "rpds_py-0.8.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:93d99f957a300d7a4ced41615c45aeb0343bb8f067c42b770b505de67a132346"},
+ {file = "rpds_py-0.8.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:148b0b38d719c0760e31ce9285a9872972bdd7774969a4154f40c980e5beaca7"},
+ {file = "rpds_py-0.8.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3cc5e5b5514796f45f03a568981971b12a3570f3de2e76114f7dc18d4b60a3c4"},
+ {file = "rpds_py-0.8.10-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:e8e24b210a4deb5a7744971f8f77393005bae7f873568e37dfd9effe808be7f7"},
+ {file = "rpds_py-0.8.10-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b41941583adce4242af003d2a8337b066ba6148ca435f295f31ac6d9e4ea2722"},
+ {file = "rpds_py-0.8.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c490204e16bca4f835dba8467869fe7295cdeaa096e4c5a7af97f3454a97991"},
+ {file = "rpds_py-0.8.10-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1ee45cd1d84beed6cbebc839fd85c2e70a3a1325c8cfd16b62c96e2ffb565eca"},
+ {file = "rpds_py-0.8.10-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a8ca409f1252e1220bf09c57290b76cae2f14723746215a1e0506472ebd7bdf"},
+ {file = "rpds_py-0.8.10-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96b293c0498c70162effb13100624c5863797d99df75f2f647438bd10cbf73e4"},
+ {file = "rpds_py-0.8.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4627520a02fccbd324b33c7a83e5d7906ec746e1083a9ac93c41ac7d15548c7"},
+ {file = "rpds_py-0.8.10-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e39d7ab0c18ac99955b36cd19f43926450baba21e3250f053e0704d6ffd76873"},
+ {file = "rpds_py-0.8.10-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ba9f1d1ebe4b63801977cec7401f2d41e888128ae40b5441270d43140efcad52"},
+ {file = "rpds_py-0.8.10-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:802f42200d8caf7f25bbb2a6464cbd83e69d600151b7e3b49f49a47fa56b0a38"},
+ {file = "rpds_py-0.8.10-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:d19db6ba816e7f59fc806c690918da80a7d186f00247048cd833acdab9b4847b"},
+ {file = "rpds_py-0.8.10-cp38-none-win32.whl", hash = "sha256:7947e6e2c2ad68b1c12ee797d15e5f8d0db36331200b0346871492784083b0c6"},
+ {file = "rpds_py-0.8.10-cp38-none-win_amd64.whl", hash = "sha256:fa326b3505d5784436d9433b7980171ab2375535d93dd63fbcd20af2b5ca1bb6"},
+ {file = "rpds_py-0.8.10-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:7b38a9ac96eeb6613e7f312cd0014de64c3f07000e8bf0004ad6ec153bac46f8"},
+ {file = "rpds_py-0.8.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c4d42e83ddbf3445e6514f0aff96dca511421ed0392d9977d3990d9f1ba6753c"},
+ {file = "rpds_py-0.8.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b21575031478609db6dbd1f0465e739fe0e7f424a8e7e87610a6c7f68b4eb16"},
+ {file = "rpds_py-0.8.10-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:574868858a7ff6011192c023a5289158ed20e3f3b94b54f97210a773f2f22921"},
+ {file = "rpds_py-0.8.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae40f4a70a1f40939d66ecbaf8e7edc144fded190c4a45898a8cfe19d8fc85ea"},
+ {file = "rpds_py-0.8.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:37f7ee4dc86db7af3bac6d2a2cedbecb8e57ce4ed081f6464510e537589f8b1e"},
+ {file = "rpds_py-0.8.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:695f642a3a5dbd4ad2ffbbacf784716ecd87f1b7a460843b9ddf965ccaeafff4"},
+ {file = "rpds_py-0.8.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f43ab4cb04bde6109eb2555528a64dfd8a265cc6a9920a67dcbde13ef53a46c8"},
+ {file = "rpds_py-0.8.10-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a11ab0d97be374efd04f640c04fe5c2d3dabc6dfb998954ea946ee3aec97056d"},
+ {file = "rpds_py-0.8.10-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:92cf5b3ee60eef41f41e1a2cabca466846fb22f37fc580ffbcb934d1bcab225a"},
+ {file = "rpds_py-0.8.10-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ceaac0c603bf5ac2f505a78b2dcab78d3e6b706be6596c8364b64cc613d208d2"},
+ {file = "rpds_py-0.8.10-cp39-none-win32.whl", hash = "sha256:dd4f16e57c12c0ae17606c53d1b57d8d1c8792efe3f065a37cb3341340599d49"},
+ {file = "rpds_py-0.8.10-cp39-none-win_amd64.whl", hash = "sha256:c03a435d26c3999c2a8642cecad5d1c4d10c961817536af52035f6f4ee2f5dd0"},
+ {file = "rpds_py-0.8.10-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:0da53292edafecba5e1d8c1218f99babf2ed0bf1c791d83c0ab5c29b57223068"},
+ {file = "rpds_py-0.8.10-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:7d20a8ed227683401cc508e7be58cba90cc97f784ea8b039c8cd01111e6043e0"},
+ {file = "rpds_py-0.8.10-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97cab733d303252f7c2f7052bf021a3469d764fc2b65e6dbef5af3cbf89d4892"},
+ {file = "rpds_py-0.8.10-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8c398fda6df361a30935ab4c4bccb7f7a3daef2964ca237f607c90e9f3fdf66f"},
+ {file = "rpds_py-0.8.10-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2eb4b08c45f8f8d8254cdbfacd3fc5d6b415d64487fb30d7380b0d0569837bf1"},
+ {file = "rpds_py-0.8.10-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e7dfb1cbb895810fa2b892b68153c17716c6abaa22c7dc2b2f6dcf3364932a1c"},
+ {file = "rpds_py-0.8.10-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89c92b74e8bf6f53a6f4995fd52f4bd510c12f103ee62c99e22bc9e05d45583c"},
+ {file = "rpds_py-0.8.10-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e9c0683cb35a9b5881b41bc01d5568ffc667910d9dbc632a1fba4e7d59e98773"},
+ {file = "rpds_py-0.8.10-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:0eeb2731708207d0fe2619afe6c4dc8cb9798f7de052da891de5f19c0006c315"},
+ {file = "rpds_py-0.8.10-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:7495010b658ec5b52835f21d8c8b1a7e52e194c50f095d4223c0b96c3da704b1"},
+ {file = "rpds_py-0.8.10-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c72ebc22e70e04126158c46ba56b85372bc4d54d00d296be060b0db1671638a4"},
+ {file = "rpds_py-0.8.10-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:2cd3045e7f6375dda64ed7db1c5136826facb0159ea982f77d9cf6125025bd34"},
+ {file = "rpds_py-0.8.10-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:2418cf17d653d24ffb8b75e81f9f60b7ba1b009a23298a433a4720b2a0a17017"},
+ {file = "rpds_py-0.8.10-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a2edf8173ac0c7a19da21bc68818be1321998528b5e3f748d6ee90c0ba2a1fd"},
+ {file = "rpds_py-0.8.10-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f29b8c55fd3a2bc48e485e37c4e2df3317f43b5cc6c4b6631c33726f52ffbb3"},
+ {file = "rpds_py-0.8.10-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a7d20c1cf8d7b3960c5072c265ec47b3f72a0c608a9a6ee0103189b4f28d531"},
+ {file = "rpds_py-0.8.10-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:521fc8861a86ae54359edf53a15a05fabc10593cea7b3357574132f8427a5e5a"},
+ {file = "rpds_py-0.8.10-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5c191713e98e7c28800233f039a32a42c1a4f9a001a8a0f2448b07391881036"},
+ {file = "rpds_py-0.8.10-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:083df0fafe199371206111583c686c985dddaf95ab3ee8e7b24f1fda54515d09"},
+ {file = "rpds_py-0.8.10-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:ed41f3f49507936a6fe7003985ea2574daccfef999775525d79eb67344e23767"},
+ {file = "rpds_py-0.8.10-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:2614c2732bf45de5c7f9e9e54e18bc78693fa2f635ae58d2895b7965e470378c"},
+ {file = "rpds_py-0.8.10-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c60528671d9d467009a6ec284582179f6b88651e83367d0ab54cb739021cd7de"},
+ {file = "rpds_py-0.8.10-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:ee744fca8d1ea822480a2a4e7c5f2e1950745477143668f0b523769426060f29"},
+ {file = "rpds_py-0.8.10-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a38b9f526d0d6cbdaa37808c400e3d9f9473ac4ff64d33d9163fd05d243dbd9b"},
+ {file = "rpds_py-0.8.10-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60e0e86e870350e03b3e25f9b1dd2c6cc72d2b5f24e070249418320a6f9097b7"},
+ {file = "rpds_py-0.8.10-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f53f55a8852f0e49b0fc76f2412045d6ad9d5772251dea8f55ea45021616e7d5"},
+ {file = "rpds_py-0.8.10-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c493365d3fad241d52f096e4995475a60a80f4eba4d3ff89b713bc65c2ca9615"},
+ {file = "rpds_py-0.8.10-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:300eb606e6b94a7a26f11c8cc8ee59e295c6649bd927f91e1dbd37a4c89430b6"},
+ {file = "rpds_py-0.8.10-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a665f6f1a87614d1c3039baf44109094926dedf785e346d8b0a728e9cabd27a"},
+ {file = "rpds_py-0.8.10-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:927d784648211447201d4c6f1babddb7971abad922b32257ab74de2f2750fad0"},
+ {file = "rpds_py-0.8.10-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:c200b30dd573afa83847bed7e3041aa36a8145221bf0cfdfaa62d974d720805c"},
+ {file = "rpds_py-0.8.10-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:08166467258fd0240a1256fce272f689f2360227ee41c72aeea103e9e4f63d2b"},
+ {file = "rpds_py-0.8.10-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:996cc95830de9bc22b183661d95559ec6b3cd900ad7bc9154c4cbf5be0c9b734"},
+ {file = "rpds_py-0.8.10.tar.gz", hash = "sha256:13e643ce8ad502a0263397362fb887594b49cf84bf518d6038c16f235f2bcea4"},
+]
+
+[[package]]
+name = "rsa"
+version = "4.9"
+description = "Pure-Python RSA implementation"
+optional = false
+python-versions = ">=3.6,<4"
+files = [
+ {file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"},
+ {file = "rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"},
+]
+
+[package.dependencies]
+pyasn1 = ">=0.1.3"
+
+[[package]]
+name = "s3transfer"
+version = "0.6.1"
+description = "An Amazon S3 Transfer Manager"
+optional = false
+python-versions = ">= 3.7"
+files = [
+ {file = "s3transfer-0.6.1-py3-none-any.whl", hash = "sha256:3c0da2d074bf35d6870ef157158641178a4204a6e689e82546083e31e0311346"},
+ {file = "s3transfer-0.6.1.tar.gz", hash = "sha256:640bb492711f4c0c0905e1f62b6aaeb771881935ad27884852411f8e9cacbca9"},
+]
+
+[package.dependencies]
+botocore = ">=1.12.36,<2.0a.0"
+
+[package.extras]
+crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"]
+
+[[package]]
+name = "sarif-om"
+version = "1.0.4"
+description = "Classes implementing the SARIF 2.1.0 object model."
+optional = false
+python-versions = ">= 2.7"
+files = [
+ {file = "sarif_om-1.0.4-py3-none-any.whl", hash = "sha256:539ef47a662329b1c8502388ad92457425e95dc0aaaf995fe46f4984c4771911"},
+ {file = "sarif_om-1.0.4.tar.gz", hash = "sha256:cd5f416b3083e00d402a92e449a7ff67af46f11241073eea0461802a3b5aef98"},
+]
+
+[package.dependencies]
+attrs = "*"
+pbr = "*"
+
+[[package]]
+name = "setuptools"
+version = "68.0.0"
+description = "Easily download, build, install, upgrade, and uninstall Python packages"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "setuptools-68.0.0-py3-none-any.whl", hash = "sha256:11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f"},
+ {file = "setuptools-68.0.0.tar.gz", hash = "sha256:baf1fdb41c6da4cd2eae722e135500da913332ab3f2f5c7d33af9b492acb5235"},
+]
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
+testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
+testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
+
+[[package]]
+name = "six"
+version = "1.16.0"
+description = "Python 2 and 3 compatibility utilities"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
+files = [
+ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
+ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
+]
+
+[[package]]
+name = "sshpubkeys"
+version = "3.3.1"
+description = "SSH public key parser"
+optional = false
+python-versions = ">=3"
+files = [
+ {file = "sshpubkeys-3.3.1-py2.py3-none-any.whl", hash = "sha256:946f76b8fe86704b0e7c56a00d80294e39bc2305999844f079a217885060b1ac"},
+ {file = "sshpubkeys-3.3.1.tar.gz", hash = "sha256:3020ed4f8c846849299370fbe98ff4157b0ccc1accec105e07cfa9ae4bb55064"},
+]
+
+[package.dependencies]
+cryptography = ">=2.1.4"
+ecdsa = ">=0.13"
+
+[package.extras]
+dev = ["twine", "wheel", "yapf"]
+
+[[package]]
+name = "sympy"
+version = "1.12"
+description = "Computer algebra system (CAS) in Python"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "sympy-1.12-py3-none-any.whl", hash = "sha256:c3588cd4295d0c0f603d0f2ae780587e64e2efeedb3521e46b9bb1d08d184fa5"},
+ {file = "sympy-1.12.tar.gz", hash = "sha256:ebf595c8dac3e0fdc4152c51878b498396ec7f30e7a914d6071e674d49420fb8"},
+]
+
+[package.dependencies]
+mpmath = ">=0.19"
+
+[[package]]
+name = "tomli"
+version = "2.0.1"
+description = "A lil' TOML parser"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
+ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
+]
+
+[[package]]
+name = "types-awscrt"
+version = "0.16.23"
+description = "Type annotations and code completion for awscrt"
+optional = false
+python-versions = ">=3.7,<4.0"
+files = [
+ {file = "types_awscrt-0.16.23-py3-none-any.whl", hash = "sha256:7edec4283fec9f92574444ce45fc0be65c846056634628aee22c118712da71c4"},
+ {file = "types_awscrt-0.16.23.tar.gz", hash = "sha256:5a846b77a6d35b63ccf9d33abf386c4dfc6275f9c062bc0e234c14ea8c6013a9"},
+]
+
+[[package]]
+name = "types-jmespath"
+version = "1.0.2.6"
+description = "Typing stubs for jmespath"
+optional = false
+python-versions = "*"
+files = [
+ {file = "types-jmespath-1.0.2.6.tar.gz", hash = "sha256:4992c1f1a97ee374e3825e057b262930b36f02be71a9c3e3394d5aab5e63dc29"},
+ {file = "types_jmespath-1.0.2.6-py3-none-any.whl", hash = "sha256:867fb88e4a04f633080dc74222a0b0e9684a2e6cc7c5d3a9e57e2b8ccf40bff7"},
+]
+
+[[package]]
+name = "types-pyyaml"
+version = "6.0.12.10"
+description = "Typing stubs for PyYAML"
+optional = false
+python-versions = "*"
+files = [
+ {file = "types-PyYAML-6.0.12.10.tar.gz", hash = "sha256:ebab3d0700b946553724ae6ca636ea932c1b0868701d4af121630e78d695fc97"},
+ {file = "types_PyYAML-6.0.12.10-py3-none-any.whl", hash = "sha256:662fa444963eff9b68120d70cda1af5a5f2aa57900003c2006d7626450eaae5f"},
+]
+
+[[package]]
+name = "types-requests"
+version = "2.31.0.1"
+description = "Typing stubs for requests"
+optional = false
+python-versions = "*"
+files = [
+ {file = "types-requests-2.31.0.1.tar.gz", hash = "sha256:3de667cffa123ce698591de0ad7db034a5317457a596eb0b4944e5a9d9e8d1ac"},
+ {file = "types_requests-2.31.0.1-py3-none-any.whl", hash = "sha256:afb06ef8f25ba83d59a1d424bd7a5a939082f94b94e90ab5e6116bd2559deaa3"},
+]
+
+[package.dependencies]
+types-urllib3 = "*"
+
+[[package]]
+name = "types-s3transfer"
+version = "0.6.1"
+description = "Type annotations and code completion for s3transfer"
+optional = false
+python-versions = ">=3.7,<4.0"
+files = [
+ {file = "types_s3transfer-0.6.1-py3-none-any.whl", hash = "sha256:6d1ac1dedac750d570428362acdf60fdd4f277b0788855c3894d3226756b2bfb"},
+ {file = "types_s3transfer-0.6.1.tar.gz", hash = "sha256:75ac1d7143d58c1e6af467cfd4a96c67ee058a3adf7c249d9309999e1f5f41e4"},
+]
+
+[package.dependencies]
+types-awscrt = "*"
+
+[[package]]
+name = "types-urllib3"
+version = "1.26.25.13"
+description = "Typing stubs for urllib3"
+optional = false
+python-versions = "*"
+files = [
+ {file = "types-urllib3-1.26.25.13.tar.gz", hash = "sha256:3300538c9dc11dad32eae4827ac313f5d986b8b21494801f1bf97a1ac6c03ae5"},
+ {file = "types_urllib3-1.26.25.13-py3-none-any.whl", hash = "sha256:5dbd1d2bef14efee43f5318b5d36d805a489f6600252bb53626d4bfafd95e27c"},
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.7.1"
+description = "Backported and Experimental Type Hints for Python 3.7+"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"},
+ {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"},
+]
+
+[[package]]
+name = "urllib3"
+version = "1.26.16"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
+files = [
+ {file = "urllib3-1.26.16-py2.py3-none-any.whl", hash = "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f"},
+ {file = "urllib3-1.26.16.tar.gz", hash = "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14"},
+]
+
+[package.extras]
+brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
+secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
+socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
+
+[[package]]
+name = "websocket-client"
+version = "1.6.1"
+description = "WebSocket client for Python with low level API options"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "websocket-client-1.6.1.tar.gz", hash = "sha256:c951af98631d24f8df89ab1019fc365f2227c0892f12fd150e935607c79dd0dd"},
+ {file = "websocket_client-1.6.1-py3-none-any.whl", hash = "sha256:f1f9f2ad5291f0225a49efad77abf9e700b6fef553900623060dad6e26503b9d"},
+]
+
+[package.extras]
+docs = ["Sphinx (>=3.4)", "sphinx-rtd-theme (>=0.5)"]
+optional = ["python-socks", "wsaccel"]
+test = ["websockets"]
+
+[[package]]
+name = "werkzeug"
+version = "2.3.6"
+description = "The comprehensive WSGI web application library."
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "Werkzeug-2.3.6-py3-none-any.whl", hash = "sha256:935539fa1413afbb9195b24880778422ed620c0fc09670945185cce4d91a8890"},
+ {file = "Werkzeug-2.3.6.tar.gz", hash = "sha256:98c774df2f91b05550078891dee5f0eb0cb797a522c757a2452b9cee5b202330"},
+]
+
+[package.dependencies]
+MarkupSafe = ">=2.1.1"
+
+[package.extras]
+watchdog = ["watchdog (>=2.3)"]
+
+[[package]]
+name = "wrapt"
+version = "1.15.0"
+description = "Module for decorators, wrappers and monkey patching."
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
+files = [
+ {file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"},
+ {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29"},
+ {file = "wrapt-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2"},
+ {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46"},
+ {file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c"},
+ {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09"},
+ {file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079"},
+ {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e"},
+ {file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a"},
+ {file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"},
+ {file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"},
+ {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"},
+ {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7"},
+ {file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0"},
+ {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec"},
+ {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90"},
+ {file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975"},
+ {file = "wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1"},
+ {file = "wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e"},
+ {file = "wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7"},
+ {file = "wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72"},
+ {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb"},
+ {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e"},
+ {file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c"},
+ {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3"},
+ {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92"},
+ {file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"},
+ {file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"},
+ {file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"},
+ {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29"},
+ {file = "wrapt-1.15.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd"},
+ {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb"},
+ {file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248"},
+ {file = "wrapt-1.15.0-cp35-cp35m-win32.whl", hash = "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559"},
+ {file = "wrapt-1.15.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"},
+ {file = "wrapt-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba"},
+ {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752"},
+ {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364"},
+ {file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475"},
+ {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8"},
+ {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418"},
+ {file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2"},
+ {file = "wrapt-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1"},
+ {file = "wrapt-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420"},
+ {file = "wrapt-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317"},
+ {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e"},
+ {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e"},
+ {file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0"},
+ {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019"},
+ {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034"},
+ {file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653"},
+ {file = "wrapt-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0"},
+ {file = "wrapt-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e"},
+ {file = "wrapt-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145"},
+ {file = "wrapt-1.15.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f"},
+ {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd"},
+ {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b"},
+ {file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f"},
+ {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6"},
+ {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094"},
+ {file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7"},
+ {file = "wrapt-1.15.0-cp38-cp38-win32.whl", hash = "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b"},
+ {file = "wrapt-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1"},
+ {file = "wrapt-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86"},
+ {file = "wrapt-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c"},
+ {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d"},
+ {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc"},
+ {file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29"},
+ {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a"},
+ {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8"},
+ {file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9"},
+ {file = "wrapt-1.15.0-cp39-cp39-win32.whl", hash = "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff"},
+ {file = "wrapt-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6"},
+ {file = "wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640"},
+ {file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"},
+]
+
+[[package]]
+name = "xmltodict"
+version = "0.13.0"
+description = "Makes working with XML feel like you are working with JSON"
+optional = false
+python-versions = ">=3.4"
+files = [
+ {file = "xmltodict-0.13.0-py2.py3-none-any.whl", hash = "sha256:aa89e8fd76320154a40d19a0df04a4695fb9dc5ba977cbb68ab3e4eb225e7852"},
+ {file = "xmltodict-0.13.0.tar.gz", hash = "sha256:341595a488e3e01a85a9d8911d8912fd922ede5fecc4dce437eb4b6c8d037e56"},
+]
+
+[[package]]
+name = "zipp"
+version = "3.16.0"
+description = "Backport of pathlib-compatible object wrapper for zip files"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "zipp-3.16.0-py3-none-any.whl", hash = "sha256:5dadc3ad0a1f825fe42ce1bce0f2fc5a13af2e6b2d386af5b0ff295bc0a287d3"},
+ {file = "zipp-3.16.0.tar.gz", hash = "sha256:1876cb065531855bbe83b6c489dcf69ecc28f1068d8e95959fe8bbc77774c941"},
+]
+
+[package.extras]
+docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
+testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"]
[metadata]
lock-version = "2.0"
-python-versions = "^3.9"
-content-hash = "99e4fd0bc0ceb446e459f34df864267ba45bfb07b49890692a1abb5618206434"
+python-versions = "^3.8.1"
+content-hash = "bcc602c86adc1f49cc19ecb899d2051955e551d7a9864c25cc7c155f4074e9fa"
diff --git a/source/cli/pyproject.toml b/source/cli/pyproject.toml
index b14f8efa..2d915c3c 100644
--- a/source/cli/pyproject.toml
+++ b/source/cli/pyproject.toml
@@ -1,25 +1,36 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.poetry]
name = "instance_scheduler_cli"
-version = "1.5.0"
-description = "AWS Instance Scheduler CLI"
-authors = ["AWS"]
-packages = [{ include="instance_scheduler_cli" }]
+version = "1.5.1"
+description = "Instance Scheduler on AWS CLI"
+license = "Apache-2.0"
+authors = ["Amazon Web Services"]
+homepage = "https://aws.amazon.com/solutions/implementations/instance-scheduler-on-aws/"
+repository = "https://github.com/aws-solutions/instance-scheduler-on-aws"
+documentation = "https://docs.aws.amazon.com/solutions/latest/instance-scheduler-on-aws/solution-overview.html"
[tool.poetry.scripts]
-scheduler-cli = 'instance_scheduler_cli.scheduler_cli:main'
+scheduler-cli = "instance_scheduler_cli:__main__"
[tool.poetry.dependencies]
-python = "^3.9"
-requests = "^2.28.1"
+python = "^3.8.1"
+boto3 = "^1.26.90"
jmespath = "^1.0.1"
-boto3 = "^1.26.48"
[tool.poetry.group.dev.dependencies]
-cli-test-helpers = "^3.2.0"
-pytest = "^7.2.0"
-pytest-cov = "^4.0.0"
-black = "^23.1.0"
+black = "^23.7.0"
+boto3-stubs-lite = {extras = ["cloudformation", "lambda"], version = "^1.26.90"}
+cli-test-helpers = "^3.4.0"
+flake8 = "^6.0.0"
+isort = "^5.12.0"
+moto = {extras = ["cloudformation", "lambda"], version = "^4.1.12"}
+mypy = "^1.4.1"
+pytest = "^7.4.0"
+pytest-cov = "^4.1.0"
+types-jmespath = "^1.0.2.6"
+types-requests = "^2.31.0.1"
diff --git a/source/cli/tests/conftest.py b/source/cli/tests/conftest.py
new file mode 100644
index 00000000..1fd280b9
--- /dev/null
+++ b/source/cli/tests/conftest.py
@@ -0,0 +1,14 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from os import environ
+
+from pytest import fixture
+
+
+@fixture(autouse=True)
+def aws_credentials() -> None:
+ environ["AWS_ACCESS_KEY_ID"] = "testing"
+ environ["AWS_SECRET_ACCESS_KEY"] = "testing"
+ environ["AWS_SECURITY_TOKEN"] = "testing"
+ environ["AWS_SESSION_TOKEN"] = "testing"
+ environ["AWS_DEFAULT_REGION"] = "us-east-1"
diff --git a/source/cli/tests/test_cli.py b/source/cli/tests/test_cli.py
index 7d83948e..71d13425 100644
--- a/source/cli/tests/test_cli.py
+++ b/source/cli/tests/test_cli.py
@@ -1,15 +1,18 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
-from unittest.mock import patch
-
from cli_test_helpers import shell
-def test_cli_entrypoint_exists():
+def test_cli_entrypoint_exists() -> None:
result = shell("scheduler-cli --help")
assert result.exit_code == 0
-def test_calling_with_no_args_exits_gracefully():
+def test_calling_with_no_args_exits_gracefully() -> None:
result = shell("scheduler-cli")
assert result.exit_code == 0
+
+
+def test_run_as_module() -> None:
+ result = shell("python -m instance_scheduler_cli --version")
+ assert result.exit_code == 0
diff --git a/source/cli/tests/test_enforce_headers.py b/source/cli/tests/test_enforce_headers.py
index c0baef6f..6979e50b 100644
--- a/source/cli/tests/test_enforce_headers.py
+++ b/source/cli/tests/test_enforce_headers.py
@@ -1,7 +1,10 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
+from os import scandir
+from pathlib import Path
+from typing import Iterator
-import pathlib
+optional_shebang = "#!/usr/bin/env python"
header_lines = [
"# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.",
@@ -9,12 +12,36 @@
]
+def valid_header(path: Path) -> bool:
+ header_length = len(header_lines)
+ lines = []
+ with open(path) as f:
+ for _ in range(header_length + 1):
+ lines.append(f.readline())
+ line_index = 0
+ if lines[0].strip() == optional_shebang:
+ line_index = 1
+ for header_line in header_lines:
+ if lines[line_index].strip() != header_line:
+ return False
+ line_index += 1
+ return True
+
+
+exclude_dirs = {".tox", ".mypy_cache"}
+
+
+def python_source_files(path: str) -> Iterator[Path]:
+ for file in Path(path).glob("*.py"):
+ if file.stat().st_size > 0:
+ yield file
+ for entry in scandir(path):
+ if entry.is_dir() and entry.name not in exclude_dirs:
+ yield from python_source_files(entry.path)
+
+
def test_headers_exist() -> None:
- for path in pathlib.Path(".").glob("**/*.py"):
- if path.stat().st_size > 0:
- with open(path) as f:
- print(path)
- for line in header_lines:
- assert (
- f.readline().strip() == line
- ), f"{path} does not contain a valid copyright header"
+ for file_path in python_source_files("."):
+ assert valid_header(
+ file_path
+ ), f"{file_path} does not contain a valid copyright header"
diff --git a/source/cli/tests/test_service_client.py b/source/cli/tests/test_service_client.py
new file mode 100644
index 00000000..ca6e34c8
--- /dev/null
+++ b/source/cli/tests/test_service_client.py
@@ -0,0 +1,18 @@
+# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0
+from typing import TYPE_CHECKING
+
+from moto import mock_cloudformation
+
+from instance_scheduler_cli.scheduler_cli import _service_client
+
+if TYPE_CHECKING:
+ from mypy_boto3_cloudformation import CloudFormationClient
+else:
+ CloudFormationClient = object
+
+
+def test_service_client() -> None:
+ with mock_cloudformation():
+ client: CloudFormationClient = _service_client("cloudformation")
+ assert client.describe_stacks()["Stacks"] == []
diff --git a/source/cli/tests/test_version.py b/source/cli/tests/test_version.py
index 9dc6a95d..e06dbda5 100644
--- a/source/cli/tests/test_version.py
+++ b/source/cli/tests/test_version.py
@@ -1,8 +1,9 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
+from importlib.metadata import version
from instance_scheduler_cli import __version__
-def test_version_correctly_picked_up_from_toml():
- assert __version__ == "1.5.0"
+def test_version_correctly_picked_up_from_toml() -> None:
+ assert __version__ == version("instance_scheduler_cli")
diff --git a/source/cli/tox.ini b/source/cli/tox.ini
new file mode 100644
index 00000000..23ba185c
--- /dev/null
+++ b/source/cli/tox.ini
@@ -0,0 +1,40 @@
+; Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+; SPDX-License-Identifier: Apache-2.0
+[tox]
+env_list = format, lint, py310-report, py3{8,9,11}-noreport
+minversion = 4.0.13
+isolated_build = true
+
+[testenv:format]
+skip_install = true
+deps =
+ black
+ isort
+commands =
+ isort --profile black --check .
+ black --check .
+
+[flake8]
+extend-ignore =
+ # line length, handled by black
+ E501,
+ # whitespace, handled by black
+ E203
+
+[testenv:lint]
+allowlist_externals = poetry
+deps = poetry
+commands_pre = poetry install
+commands =
+ poetry run mypy .
+ poetry run flake8 .
+
+[testenv:py3{8,9,10,11}-{report, noreport}]
+allowlist_externals = poetry
+deps = poetry
+pass_env = PYTHON_VERSION
+package = skip
+commands_pre = poetry install
+commands =
+ report: poetry run pytest tests/ {posargs}
+ noreport: poetry run pytest tests/
diff --git a/source/infrastructure/README.md b/source/infrastructure/README.md
deleted file mode 100644
index d2bb62aa..00000000
--- a/source/infrastructure/README.md
+++ /dev/null
@@ -1,22 +0,0 @@
-# AWS Instance Scheduler CDK TypeScript project!
-
-AWS Instance Scheduler is modified to utilize AWS CDK for generating the cloudformation templates, this project is based CDK Typescript project structure.
-
-## Useful commands
-
-- `npm run build` compile typescript to js
-- `npm run watch` watch for changes and compile
-- `npm run test` perform the jest unit tests
-- `cdk deploy` deploy this stack to your default AWS account/region
-- `cdk diff` compare deployed stack with current state
-- `cdk synth` emits the synthesized CloudFormation template
-
----
-
-Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
-
-Licensed under the Apache License Version 2.0 (the "License"). You may not use this file except in compliance with the License. A copy of the License is located at
-
- http://www.apache.org/licenses/
-
-or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions and limitations under the License.
diff --git a/source/infrastructure/instance-scheduler/bin/aws-instance-scheduler.ts b/source/infrastructure/instance-scheduler/bin/aws-instance-scheduler.ts
deleted file mode 100644
index 91fc70a2..00000000
--- a/source/infrastructure/instance-scheduler/bin/aws-instance-scheduler.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/usr/bin/env node
-// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-// SPDX-License-Identifier: Apache-2.0
-
-import * as cdk from "aws-cdk-lib";
-import { AwsInstanceSchedulerStack } from "../lib/aws-instance-scheduler-stack";
-import { AwsInstanceSchedulerRemoteStack } from "../lib/aws-instance-scheduler-remote-stack";
-import { Aspects, DefaultStackSynthesizer } from "aws-cdk-lib";
-import { AwsSolutionsChecks, NagSuppressions } from "cdk-nag";
-import { getSolutionContext } from "./cdk-context";
-
-let synthesizer = new DefaultStackSynthesizer({
- generateBootstrapVersionRule: false,
-});
-
-// Solutions pipeline deployment
-const { DIST_OUTPUT_BUCKET, SOLUTION_NAME, DIST_VERSION } = process.env;
-if (DIST_OUTPUT_BUCKET && SOLUTION_NAME && DIST_VERSION) {
- synthesizer = new DefaultStackSynthesizer({
- generateBootstrapVersionRule: false,
- fileAssetsBucketName: `${DIST_OUTPUT_BUCKET}-\${AWS::Region}`,
- bucketPrefix: `${SOLUTION_NAME}/${DIST_VERSION}/`,
- });
-}
-
-const app = new cdk.App();
-const solutionDetails = getSolutionContext(app);
-
-const hubStack = new AwsInstanceSchedulerStack(app, "aws-instance-scheduler", {
- synthesizer: synthesizer,
- description: `(${solutionDetails.solutionId}) - The AWS CloudFormation template for deployment of the ${solutionDetails.solutionName}, version: ${solutionDetails.solutionVersion}`,
- solutionId: solutionDetails.solutionId,
- solutionName: solutionDetails.solutionName,
- solutionVersion: solutionDetails.solutionVersion,
- appregApplicationName: solutionDetails.appRegAppName,
- appregSolutionName: solutionDetails.appRegSolutionName,
-});
-
-new AwsInstanceSchedulerRemoteStack(app, "aws-instance-scheduler-remote", {
- synthesizer: synthesizer,
- description: `(${solutionDetails.solutionId}S) - The AWS CloudFormation template for ${solutionDetails.solutionName} cross account role, version: ${solutionDetails.solutionVersion}`,
- solutionId: solutionDetails.solutionId,
- solutionName: solutionDetails.solutionName,
- solutionVersion: solutionDetails.solutionVersion,
- appregApplicationName: solutionDetails.appRegAppName,
- appregSolutionName: solutionDetails.appRegSolutionName,
-});
-
-NagSuppressions.addResourceSuppressionsByPath(
- hubStack,
- "/aws-instance-scheduler/SchedulerRole/DefaultPolicy/Resource",
- [
- {
- id: "AwsSolutions-IAM5",
- reason: "The scheduling lambda must access multiple resources across services",
- },
- ]
-);
-
-Aspects.of(app).add(
- new AwsSolutionsChecks({
- verbose: true,
- })
-);
diff --git a/source/infrastructure/instance-scheduler/cdk.json b/source/infrastructure/instance-scheduler/cdk.json
deleted file mode 100644
index ebbdf191..00000000
--- a/source/infrastructure/instance-scheduler/cdk.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "app": "npx ts-node bin/aws-instance-scheduler.ts",
- "output": "../../../build/cdk.out",
- "context": {
- "solutionId": "SO0030",
- "solutionVersion": "1.5.0",
- "solutionName": "aws-instance-scheduler",
- "appRegApplicationName": "AWS-Solutions",
- "appRegSolutionName": "instance-scheduler-on-aws"
- }
-}
diff --git a/source/infrastructure/instance-scheduler/jest.config.ts b/source/infrastructure/instance-scheduler/jest.config.ts
deleted file mode 100644
index d9109cd4..00000000
--- a/source/infrastructure/instance-scheduler/jest.config.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-// SPDX-License-Identifier: Apache-2.0
-module.exports = {
- roots: ["/tests"],
- testMatch: ["**/*.test.ts"],
- transform: {
- "^.+\\.tsx?$": "ts-jest",
- },
- reporters: [
- "default",
- [
- "jest-junit",
- {
- outputDirectory: "../../deployment/test-reports",
- outputName: "cdk-test-report.xml",
- },
- ],
- ],
-};
diff --git a/source/infrastructure/instance-scheduler/tests/aws-instance-scheduler-stack.test.ts b/source/infrastructure/instance-scheduler/tests/aws-instance-scheduler-stack.test.ts
deleted file mode 100644
index 8bea5a16..00000000
--- a/source/infrastructure/instance-scheduler/tests/aws-instance-scheduler-stack.test.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-// SPDX-License-Identifier: Apache-2.0
-
-import { Template } from "aws-cdk-lib/assertions";
-import { createHubStack } from "./instance-scheduler-stack-factory";
-
-/*
- * SnapShot Testing for the AwsInstanceSchedulerStack.
- */
-test("AwsInstanceSchedulerStack snapshot test", () => {
- const hubStackJson = Template.fromStack(createHubStack()).toJSON();
- hubStackJson.Resources.Main.Properties.Code = "Omitted to remove snapshot dependency on code hash";
- expect(hubStackJson).toMatchSnapshot();
-});
diff --git a/source/infrastructure/instance-scheduler/tests/instance-scheduler-stack-factory.ts b/source/infrastructure/instance-scheduler/tests/instance-scheduler-stack-factory.ts
deleted file mode 100644
index 2bdb4389..00000000
--- a/source/infrastructure/instance-scheduler/tests/instance-scheduler-stack-factory.ts
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-// SPDX-License-Identifier: Apache-2.0
-
-import * as instanceSchedulerHubStack from "../lib/aws-instance-scheduler-stack";
-import * as instanceSchedulerSpokeStack from "../lib/aws-instance-scheduler-remote-stack";
-import * as cdk from "aws-cdk-lib";
-import { DefaultStackSynthesizer } from "aws-cdk-lib";
-
-export function createHubStack(): cdk.Stack {
- const app = new cdk.App();
- const envEU = { account: "111111111111", region: "eu-west-1" };
- const stack = new instanceSchedulerHubStack.AwsInstanceSchedulerStack(app, "stack", {
- env: envEU,
- description: "",
- solutionId: "SO0030",
- solutionName: "aws-instance-scheduler",
- solutionVersion: "v1.5.0",
- appregApplicationName: "AWS-Solutions",
- appregSolutionName: "instance-scheduler-on-aws",
- synthesizer: new DefaultStackSynthesizer({ generateBootstrapVersionRule: false }),
- });
-
- const instanceSchedulerStackMetadata = {
- "AWS::CloudFormation::Interface": {
- ParameterGroups: [
- {
- Label: {
- default: "Scheduler (version v1.4.0)",
- },
- Parameters: [
- "TagName",
- "ScheduledServices",
- "ScheduleRdsClusters",
- "CreateRdsSnapshot",
- "SchedulingActive",
- "Regions",
- "DefaultTimezone",
- "CrossAccountRoles",
- "ScheduleLambdaAccount",
- "SchedulerFrequency",
- "MemorySize",
- ],
- },
- {
- Label: {
- default: "Options",
- },
- Parameters: ["UseCloudWatchMetrics", "SendAnonymousData", "Trace"],
- },
- {
- Label: {
- default: "Other parameters",
- },
- Parameters: ["LogRetentionDays", "StartedTags", "StoppedTags"],
- },
- ],
- ParameterLabels: {
- LogRetentionDays: {
- default: "Log retention days",
- },
- StartedTags: {
- default: "Started tags",
- },
- StoppedTags: {
- default: "Stopped tags",
- },
- SchedulingActive: {
- default: "Scheduling enabled",
- },
- CrossAccountRoles: {
- default: "Cross-account roles",
- },
- ScheduleLambdaAccount: {
- default: "This account",
- },
- UseCloudWatchMetrics: {
- default: "Enable CloudWatch Metrics",
- },
- Trace: {
- default: "Enable CloudWatch Logs",
- },
- TagName: {
- default: "Instance Scheduler tag name",
- },
- ScheduledServices: {
- default: "Service(s) to schedule",
- },
- ScheduleRdsClusters: {
- default: "Schedule Aurora Clusters",
- },
- CreateRdsSnapshot: {
- default: "Create RDS instance snapshot",
- },
- DefaultTimezone: {
- default: "Default time zone",
- },
- SchedulerFrequency: {
- default: "Frequency",
- },
- Regions: {
- default: "Region(s)",
- },
- MemorySize: {
- default: "Memory size",
- },
- SendAnonymousData: {
- default: "Send anonymous usage data",
- },
- },
- },
- };
- stack.templateOptions.metadata = instanceSchedulerStackMetadata;
- stack.templateOptions.templateFormatVersion = "2010-09-09";
- return stack;
-}
-
-export function createSpokeStack(): cdk.Stack {
- const envEU = { account: "111111111111", region: "eu-west-1" };
- const app = new cdk.App();
- const stack = new instanceSchedulerSpokeStack.AwsInstanceSchedulerRemoteStack(app, "stack", {
- env: envEU,
- description: "",
- solutionId: "SO0030",
- solutionName: "aws-instance-scheduler",
- solutionVersion: "v1.5.0",
- appregApplicationName: "AWS-Solutions",
- appregSolutionName: "instance-scheduler-on-aws",
- synthesizer: new DefaultStackSynthesizer({ generateBootstrapVersionRule: false }),
- });
-
- const instanceSchedulerRemoteStackMetadata = {
- "AWS::CloudFormation::Interface": {
- ParameterGroups: [
- {
- Label: {
- default: "Account",
- },
- Parameters: ["InstanceSchedulerAccount"],
- },
- ],
- ParameterLabels: {
- InstanceSchedulerAccount: {
- default: "Primary account",
- },
- },
- },
- };
- stack.templateOptions.metadata = instanceSchedulerRemoteStackMetadata;
- stack.templateOptions.templateFormatVersion = "2010-09-09";
- return stack;
-}
diff --git a/source/infrastructure/package-lock.json b/source/infrastructure/package-lock.json
deleted file mode 100644
index 698ffdc6..00000000
--- a/source/infrastructure/package-lock.json
+++ /dev/null
@@ -1,16045 +0,0 @@
-{
- "name": "aws-instance-scheduler",
- "version": "1.5.0",
- "lockfileVersion": 2,
- "requires": true,
- "packages": {
- "": {
- "name": "aws-instance-scheduler",
- "version": "1.5.0",
- "dependencies": {
- "@aws-cdk/aws-lambda-python-alpha": "~2.68.0-alpha.0",
- "@aws-cdk/aws-servicecatalogappregistry-alpha": "^2.62.2-alpha.0",
- "@aws-sdk/client-dynamodb": "^3.295.0",
- "@aws-sdk/client-ec2": "^3.295.0",
- "@aws-sdk/client-rds": "^3.314.0",
- "@aws-solutions-constructs/aws-lambda-dynamodb": "2.30.0",
- "aws-cdk-lib": "^2.62.0",
- "cdk-nag": "^2.22.23",
- "constructs": "^10.0.0",
- "source-map-support": "^0.5.16"
- },
- "bin": {
- "aws-instance-scheduler": "infrastructure/bin/aws-instance-scheduler.js"
- },
- "devDependencies": {
- "@types/jest": "^26.0.10",
- "@types/node": "10.17.27",
- "@typescript-eslint/eslint-plugin": "^5.55.0",
- "aws-cdk": "^2.68.0",
- "eslint": "^8.36.0",
- "eslint-config-prettier": "^8.7.0",
- "eslint-plugin-header": "^3.1.1",
- "eslint-plugin-import": "^2.27.5",
- "eslint-plugin-prettier": "^4.2.1",
- "jest": "^29.3.1",
- "jest-extended": "^3.2.4",
- "jest-junit": "^15.0.0",
- "ts-jest": "^29.0.3",
- "ts-node": "^10.9.1",
- "typescript": "^4.9.4"
- }
- },
- "node_modules/@ampproject/remapping": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
- "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==",
- "dev": true,
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.1.0",
- "@jridgewell/trace-mapping": "^0.3.9"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@aws-cdk/asset-awscli-v1": {
- "version": "2.2.98",
- "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.98.tgz",
- "integrity": "sha512-SRJeHb08wW5FVZN7OrbzHzyxW9HuRek2irRCUc+6YBgIRM1JYlyUSd+vcaPThTllNl7rUf4oNvmyK0/3tWLKDg=="
- },
- "node_modules/@aws-cdk/asset-kubectl-v20": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@aws-cdk/asset-kubectl-v20/-/asset-kubectl-v20-2.1.1.tgz",
- "integrity": "sha512-U1ntiX8XiMRRRH5J1IdC+1t5CE89015cwyt5U63Cpk0GnMlN5+h9WsWMlKlPXZR4rdq/m806JRlBMRpBUB2Dhw=="
- },
- "node_modules/@aws-cdk/asset-node-proxy-agent-v5": {
- "version": "2.0.78",
- "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v5/-/asset-node-proxy-agent-v5-2.0.78.tgz",
- "integrity": "sha512-NMGFaszbLkLQlxIJ0ydyO+P78cgTEUleGt1nn3CSRyuBHoYkHNGAcY2JUxTFhQc3/AZuq1x4w87zqh7eAOTyTw=="
- },
- "node_modules/@aws-cdk/aws-lambda-python-alpha": {
- "version": "2.68.0-alpha.0",
- "resolved": "https://registry.npmjs.org/@aws-cdk/aws-lambda-python-alpha/-/aws-lambda-python-alpha-2.68.0-alpha.0.tgz",
- "integrity": "sha512-rWKI4kLIblfGXMmJ6fH07CMnktbpWqJTatP80qwbBGbLclSPwIQi4hcP2T6gMdR/1mHybR0LyXzfKON34k/KJg==",
- "engines": {
- "node": ">= 14.15.0"
- },
- "peerDependencies": {
- "aws-cdk-lib": "^2.68.0",
- "constructs": "^10.0.0"
- }
- },
- "node_modules/@aws-cdk/aws-servicecatalogappregistry-alpha": {
- "version": "2.62.2-alpha.0",
- "resolved": "https://registry.npmjs.org/@aws-cdk/aws-servicecatalogappregistry-alpha/-/aws-servicecatalogappregistry-alpha-2.62.2-alpha.0.tgz",
- "integrity": "sha512-ziMXproSFdqwpVBqVOD2vsCqqmGKxJTd9xzrT3MasCowA0M0fYUSk2IjdXvEGlRzGviCm0wjcKfrDqNIfqqXuA==",
- "engines": {
- "node": ">= 14.15.0"
- },
- "peerDependencies": {
- "aws-cdk-lib": "^2.62.2",
- "constructs": "^10.0.0"
- }
- },
- "node_modules/@aws-crypto/ie11-detection": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz",
- "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==",
- "dependencies": {
- "tslib": "^1.11.1"
- }
- },
- "node_modules/@aws-crypto/ie11-detection/node_modules/tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- },
- "node_modules/@aws-crypto/sha256-browser": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz",
- "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==",
- "dependencies": {
- "@aws-crypto/ie11-detection": "^3.0.0",
- "@aws-crypto/sha256-js": "^3.0.0",
- "@aws-crypto/supports-web-crypto": "^3.0.0",
- "@aws-crypto/util": "^3.0.0",
- "@aws-sdk/types": "^3.222.0",
- "@aws-sdk/util-locate-window": "^3.0.0",
- "@aws-sdk/util-utf8-browser": "^3.0.0",
- "tslib": "^1.11.1"
- }
- },
- "node_modules/@aws-crypto/sha256-browser/node_modules/tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- },
- "node_modules/@aws-crypto/sha256-js": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz",
- "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==",
- "dependencies": {
- "@aws-crypto/util": "^3.0.0",
- "@aws-sdk/types": "^3.222.0",
- "tslib": "^1.11.1"
- }
- },
- "node_modules/@aws-crypto/sha256-js/node_modules/tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- },
- "node_modules/@aws-crypto/supports-web-crypto": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz",
- "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==",
- "dependencies": {
- "tslib": "^1.11.1"
- }
- },
- "node_modules/@aws-crypto/supports-web-crypto/node_modules/tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- },
- "node_modules/@aws-crypto/util": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz",
- "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==",
- "dependencies": {
- "@aws-sdk/types": "^3.222.0",
- "@aws-sdk/util-utf8-browser": "^3.0.0",
- "tslib": "^1.11.1"
- }
- },
- "node_modules/@aws-crypto/util/node_modules/tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- },
- "node_modules/@aws-sdk/abort-controller": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.295.0.tgz",
- "integrity": "sha512-uohsGotvQ8RTgVZ9sQt0y3L60jBEYgN8MOn3Seaku8HpIIo9c6iIfkF0bMXZeFI2sCxqbrBDbsPKYWxr7rd8LA==",
- "dependencies": {
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-dynamodb": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.295.0.tgz",
- "integrity": "sha512-upUEezK2P1c8GqwFG3h4vMXzjDHGyZvlGoiOPytrz4akmP4p120+cJjCwNFHJmG5TqSUCJUhZ/gMjF5ku1eosg==",
- "dependencies": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/client-sts": "3.295.0",
- "@aws-sdk/config-resolver": "3.295.0",
- "@aws-sdk/credential-provider-node": "3.295.0",
- "@aws-sdk/fetch-http-handler": "3.295.0",
- "@aws-sdk/hash-node": "3.295.0",
- "@aws-sdk/invalid-dependency": "3.295.0",
- "@aws-sdk/middleware-content-length": "3.295.0",
- "@aws-sdk/middleware-endpoint": "3.295.0",
- "@aws-sdk/middleware-endpoint-discovery": "3.295.0",
- "@aws-sdk/middleware-host-header": "3.295.0",
- "@aws-sdk/middleware-logger": "3.295.0",
- "@aws-sdk/middleware-recursion-detection": "3.295.0",
- "@aws-sdk/middleware-retry": "3.295.0",
- "@aws-sdk/middleware-serde": "3.295.0",
- "@aws-sdk/middleware-signing": "3.295.0",
- "@aws-sdk/middleware-stack": "3.295.0",
- "@aws-sdk/middleware-user-agent": "3.295.0",
- "@aws-sdk/node-config-provider": "3.295.0",
- "@aws-sdk/node-http-handler": "3.295.0",
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/smithy-client": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/url-parser": "3.295.0",
- "@aws-sdk/util-base64": "3.295.0",
- "@aws-sdk/util-body-length-browser": "3.295.0",
- "@aws-sdk/util-body-length-node": "3.295.0",
- "@aws-sdk/util-defaults-mode-browser": "3.295.0",
- "@aws-sdk/util-defaults-mode-node": "3.295.0",
- "@aws-sdk/util-endpoints": "3.295.0",
- "@aws-sdk/util-retry": "3.295.0",
- "@aws-sdk/util-user-agent-browser": "3.295.0",
- "@aws-sdk/util-user-agent-node": "3.295.0",
- "@aws-sdk/util-utf8": "3.295.0",
- "@aws-sdk/util-waiter": "3.295.0",
- "tslib": "^2.5.0",
- "uuid": "^8.3.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-ec2": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-ec2/-/client-ec2-3.295.0.tgz",
- "integrity": "sha512-F2abZUElpiJvr4d5AUVODbgFPD8UMniFpAYb2Y1TruBR7d6gF9RDJ8jm5Epsg1tlL511kJBouREFID5bWQba3w==",
- "dependencies": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/client-sts": "3.295.0",
- "@aws-sdk/config-resolver": "3.295.0",
- "@aws-sdk/credential-provider-node": "3.295.0",
- "@aws-sdk/fetch-http-handler": "3.295.0",
- "@aws-sdk/hash-node": "3.295.0",
- "@aws-sdk/invalid-dependency": "3.295.0",
- "@aws-sdk/middleware-content-length": "3.295.0",
- "@aws-sdk/middleware-endpoint": "3.295.0",
- "@aws-sdk/middleware-host-header": "3.295.0",
- "@aws-sdk/middleware-logger": "3.295.0",
- "@aws-sdk/middleware-recursion-detection": "3.295.0",
- "@aws-sdk/middleware-retry": "3.295.0",
- "@aws-sdk/middleware-sdk-ec2": "3.295.0",
- "@aws-sdk/middleware-serde": "3.295.0",
- "@aws-sdk/middleware-signing": "3.295.0",
- "@aws-sdk/middleware-stack": "3.295.0",
- "@aws-sdk/middleware-user-agent": "3.295.0",
- "@aws-sdk/node-config-provider": "3.295.0",
- "@aws-sdk/node-http-handler": "3.295.0",
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/smithy-client": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/url-parser": "3.295.0",
- "@aws-sdk/util-base64": "3.295.0",
- "@aws-sdk/util-body-length-browser": "3.295.0",
- "@aws-sdk/util-body-length-node": "3.295.0",
- "@aws-sdk/util-defaults-mode-browser": "3.295.0",
- "@aws-sdk/util-defaults-mode-node": "3.295.0",
- "@aws-sdk/util-endpoints": "3.295.0",
- "@aws-sdk/util-retry": "3.295.0",
- "@aws-sdk/util-user-agent-browser": "3.295.0",
- "@aws-sdk/util-user-agent-node": "3.295.0",
- "@aws-sdk/util-utf8": "3.295.0",
- "@aws-sdk/util-waiter": "3.295.0",
- "fast-xml-parser": "4.1.2",
- "tslib": "^2.5.0",
- "uuid": "^8.3.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds": {
- "version": "3.314.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-rds/-/client-rds-3.314.0.tgz",
- "integrity": "sha512-+jvimITTzmDkMNwAh2vV4+r22GZWF1TCdCiQqB1+djApmfifUFSEGyDrNRpHOKYeBhDR6mHPVC+qW5hs8XWr6A==",
- "dependencies": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/client-sts": "3.312.0",
- "@aws-sdk/config-resolver": "3.310.0",
- "@aws-sdk/credential-provider-node": "3.310.0",
- "@aws-sdk/fetch-http-handler": "3.310.0",
- "@aws-sdk/hash-node": "3.310.0",
- "@aws-sdk/invalid-dependency": "3.310.0",
- "@aws-sdk/middleware-content-length": "3.310.0",
- "@aws-sdk/middleware-endpoint": "3.310.0",
- "@aws-sdk/middleware-host-header": "3.310.0",
- "@aws-sdk/middleware-logger": "3.310.0",
- "@aws-sdk/middleware-recursion-detection": "3.310.0",
- "@aws-sdk/middleware-retry": "3.310.0",
- "@aws-sdk/middleware-sdk-rds": "3.310.0",
- "@aws-sdk/middleware-serde": "3.310.0",
- "@aws-sdk/middleware-signing": "3.310.0",
- "@aws-sdk/middleware-stack": "3.310.0",
- "@aws-sdk/middleware-user-agent": "3.310.0",
- "@aws-sdk/node-config-provider": "3.310.0",
- "@aws-sdk/node-http-handler": "3.310.0",
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/smithy-client": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/url-parser": "3.310.0",
- "@aws-sdk/util-base64": "3.310.0",
- "@aws-sdk/util-body-length-browser": "3.310.0",
- "@aws-sdk/util-body-length-node": "3.310.0",
- "@aws-sdk/util-defaults-mode-browser": "3.310.0",
- "@aws-sdk/util-defaults-mode-node": "3.310.0",
- "@aws-sdk/util-endpoints": "3.310.0",
- "@aws-sdk/util-retry": "3.310.0",
- "@aws-sdk/util-user-agent-browser": "3.310.0",
- "@aws-sdk/util-user-agent-node": "3.310.0",
- "@aws-sdk/util-utf8": "3.310.0",
- "@aws-sdk/util-waiter": "3.310.0",
- "fast-xml-parser": "4.1.2",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/abort-controller": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.310.0.tgz",
- "integrity": "sha512-v1zrRQxDLA1MdPim159Vx/CPHqsB4uybSxRi1CnfHO5ZjHryx3a5htW2gdGAykVCul40+yJXvfpufMrELVxH+g==",
- "dependencies": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/client-sso": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.310.0.tgz",
- "integrity": "sha512-netFap3Mp9I7bzAjsswHPA5WEbQtNMmXvW9/IVb7tmf85/esXCWindtyI43e/Xerut9ZVyEACPBFn30CLLE2xQ==",
- "dependencies": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/config-resolver": "3.310.0",
- "@aws-sdk/fetch-http-handler": "3.310.0",
- "@aws-sdk/hash-node": "3.310.0",
- "@aws-sdk/invalid-dependency": "3.310.0",
- "@aws-sdk/middleware-content-length": "3.310.0",
- "@aws-sdk/middleware-endpoint": "3.310.0",
- "@aws-sdk/middleware-host-header": "3.310.0",
- "@aws-sdk/middleware-logger": "3.310.0",
- "@aws-sdk/middleware-recursion-detection": "3.310.0",
- "@aws-sdk/middleware-retry": "3.310.0",
- "@aws-sdk/middleware-serde": "3.310.0",
- "@aws-sdk/middleware-stack": "3.310.0",
- "@aws-sdk/middleware-user-agent": "3.310.0",
- "@aws-sdk/node-config-provider": "3.310.0",
- "@aws-sdk/node-http-handler": "3.310.0",
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/smithy-client": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/url-parser": "3.310.0",
- "@aws-sdk/util-base64": "3.310.0",
- "@aws-sdk/util-body-length-browser": "3.310.0",
- "@aws-sdk/util-body-length-node": "3.310.0",
- "@aws-sdk/util-defaults-mode-browser": "3.310.0",
- "@aws-sdk/util-defaults-mode-node": "3.310.0",
- "@aws-sdk/util-endpoints": "3.310.0",
- "@aws-sdk/util-retry": "3.310.0",
- "@aws-sdk/util-user-agent-browser": "3.310.0",
- "@aws-sdk/util-user-agent-node": "3.310.0",
- "@aws-sdk/util-utf8": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/client-sso-oidc": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.310.0.tgz",
- "integrity": "sha512-3GKaRSfMD3OiYWGa+qg5KvJw0nLV0Vu7zRiulLuKDvgmWw3SNJKn3frWlmq/bKFUKahLsV8zozbeJItxtKAD6g==",
- "dependencies": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/config-resolver": "3.310.0",
- "@aws-sdk/fetch-http-handler": "3.310.0",
- "@aws-sdk/hash-node": "3.310.0",
- "@aws-sdk/invalid-dependency": "3.310.0",
- "@aws-sdk/middleware-content-length": "3.310.0",
- "@aws-sdk/middleware-endpoint": "3.310.0",
- "@aws-sdk/middleware-host-header": "3.310.0",
- "@aws-sdk/middleware-logger": "3.310.0",
- "@aws-sdk/middleware-recursion-detection": "3.310.0",
- "@aws-sdk/middleware-retry": "3.310.0",
- "@aws-sdk/middleware-serde": "3.310.0",
- "@aws-sdk/middleware-stack": "3.310.0",
- "@aws-sdk/middleware-user-agent": "3.310.0",
- "@aws-sdk/node-config-provider": "3.310.0",
- "@aws-sdk/node-http-handler": "3.310.0",
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/smithy-client": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/url-parser": "3.310.0",
- "@aws-sdk/util-base64": "3.310.0",
- "@aws-sdk/util-body-length-browser": "3.310.0",
- "@aws-sdk/util-body-length-node": "3.310.0",
- "@aws-sdk/util-defaults-mode-browser": "3.310.0",
- "@aws-sdk/util-defaults-mode-node": "3.310.0",
- "@aws-sdk/util-endpoints": "3.310.0",
- "@aws-sdk/util-retry": "3.310.0",
- "@aws-sdk/util-user-agent-browser": "3.310.0",
- "@aws-sdk/util-user-agent-node": "3.310.0",
- "@aws-sdk/util-utf8": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/client-sts": {
- "version": "3.312.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.312.0.tgz",
- "integrity": "sha512-t0U7vRvWaMjrzBUo6tPrHe6HE97Blqx+b4GOjFbcbLtzxLlcRfhnWJik0Lp8hJtVqzNoN5mL4OeYgK7CRpL/Sw==",
- "dependencies": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/config-resolver": "3.310.0",
- "@aws-sdk/credential-provider-node": "3.310.0",
- "@aws-sdk/fetch-http-handler": "3.310.0",
- "@aws-sdk/hash-node": "3.310.0",
- "@aws-sdk/invalid-dependency": "3.310.0",
- "@aws-sdk/middleware-content-length": "3.310.0",
- "@aws-sdk/middleware-endpoint": "3.310.0",
- "@aws-sdk/middleware-host-header": "3.310.0",
- "@aws-sdk/middleware-logger": "3.310.0",
- "@aws-sdk/middleware-recursion-detection": "3.310.0",
- "@aws-sdk/middleware-retry": "3.310.0",
- "@aws-sdk/middleware-sdk-sts": "3.310.0",
- "@aws-sdk/middleware-serde": "3.310.0",
- "@aws-sdk/middleware-signing": "3.310.0",
- "@aws-sdk/middleware-stack": "3.310.0",
- "@aws-sdk/middleware-user-agent": "3.310.0",
- "@aws-sdk/node-config-provider": "3.310.0",
- "@aws-sdk/node-http-handler": "3.310.0",
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/smithy-client": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/url-parser": "3.310.0",
- "@aws-sdk/util-base64": "3.310.0",
- "@aws-sdk/util-body-length-browser": "3.310.0",
- "@aws-sdk/util-body-length-node": "3.310.0",
- "@aws-sdk/util-defaults-mode-browser": "3.310.0",
- "@aws-sdk/util-defaults-mode-node": "3.310.0",
- "@aws-sdk/util-endpoints": "3.310.0",
- "@aws-sdk/util-retry": "3.310.0",
- "@aws-sdk/util-user-agent-browser": "3.310.0",
- "@aws-sdk/util-user-agent-node": "3.310.0",
- "@aws-sdk/util-utf8": "3.310.0",
- "fast-xml-parser": "4.1.2",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/config-resolver": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.310.0.tgz",
- "integrity": "sha512-8vsT+/50lOqfDxka9m/rRt6oxv1WuGZoP8oPMk0Dt+TxXMbAzf4+rejBgiB96wshI1k3gLokYRjSQZn+dDtT8g==",
- "dependencies": {
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/util-config-provider": "3.310.0",
- "@aws-sdk/util-middleware": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/credential-provider-env": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.310.0.tgz",
- "integrity": "sha512-vvIPQpI16fj95xwS7M3D48F7QhZJBnnCgB5lR+b7So+vsG9ibm1mZRVGzVpdxCvgyOhHFbvrby9aalNJmmIP1A==",
- "dependencies": {
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/credential-provider-imds": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.310.0.tgz",
- "integrity": "sha512-baxK7Zp6dai5AGW01FIW27xS2KAaPUmKLIXv5SvFYsUgXXvNW55im4uG3b+2gA0F7V+hXvVBH08OEqmwW6we5w==",
- "dependencies": {
- "@aws-sdk/node-config-provider": "3.310.0",
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/url-parser": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/credential-provider-ini": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.310.0.tgz",
- "integrity": "sha512-gtRz7I+4BBpwZ3tc6UIt5lQuiAFnkpOibxHh95x1M6HDxBjm+uqD6RPZYVH+dULZPYXOtOTsHV0IGjrcV0sSRg==",
- "dependencies": {
- "@aws-sdk/credential-provider-env": "3.310.0",
- "@aws-sdk/credential-provider-imds": "3.310.0",
- "@aws-sdk/credential-provider-process": "3.310.0",
- "@aws-sdk/credential-provider-sso": "3.310.0",
- "@aws-sdk/credential-provider-web-identity": "3.310.0",
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/shared-ini-file-loader": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/credential-provider-node": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.310.0.tgz",
- "integrity": "sha512-FrOztUcOq2Sp32xGtJvxfvdlmuAeoxIu/AElHzV1bkx6Pzo9DkQBhXrSQ+JFSpI++weOD4ZGFhAvgbgUOT4VAg==",
- "dependencies": {
- "@aws-sdk/credential-provider-env": "3.310.0",
- "@aws-sdk/credential-provider-imds": "3.310.0",
- "@aws-sdk/credential-provider-ini": "3.310.0",
- "@aws-sdk/credential-provider-process": "3.310.0",
- "@aws-sdk/credential-provider-sso": "3.310.0",
- "@aws-sdk/credential-provider-web-identity": "3.310.0",
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/shared-ini-file-loader": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/credential-provider-process": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.310.0.tgz",
- "integrity": "sha512-h73sg6GPMUWC+3zMCbA1nZ2O03nNJt7G96JdmnantiXBwHpRKWW8nBTLzx5uhXn6hTuTaoQRP/P+oxQJKYdMmA==",
- "dependencies": {
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/shared-ini-file-loader": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/credential-provider-sso": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.310.0.tgz",
- "integrity": "sha512-nXkpT8mrM/wRqSiz/a4p9U2UrOKyfZXhbPHIHyQj8K+uLjsYS+WPuH287J4A5Q57A6uarTrj5RjHmVeZVLaHmg==",
- "dependencies": {
- "@aws-sdk/client-sso": "3.310.0",
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/shared-ini-file-loader": "3.310.0",
- "@aws-sdk/token-providers": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/credential-provider-web-identity": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.310.0.tgz",
- "integrity": "sha512-H4SzuZXILNhK6/IR1uVvsUDZvzc051hem7GLyYghBCu8mU+tq28YhKE8MfSroi6eL2e5Vujloij1OM2EQQkPkw==",
- "dependencies": {
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/fetch-http-handler": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.310.0.tgz",
- "integrity": "sha512-Bi9vIwzdkw1zMcvi/zGzlWS9KfIEnAq4NNhsnCxbQ4OoIRU9wvU+WGZdBBhxg0ZxZmpp1j1aZhU53lLjA07MHw==",
- "dependencies": {
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/querystring-builder": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/util-base64": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/hash-node": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.310.0.tgz",
- "integrity": "sha512-NvE2fhRc8GRwCXBfDehxVAWCmVwVMILliAKVPAEr4yz2CkYs0tqU51S48x23dtna07H4qHtgpeNqVTthcIQOEQ==",
- "dependencies": {
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/util-buffer-from": "3.310.0",
- "@aws-sdk/util-utf8": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/invalid-dependency": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.310.0.tgz",
- "integrity": "sha512-1s5RG5rSPXoa/aZ/Kqr5U/7lqpx+Ry81GprQ2bxWqJvWQIJ0IRUwo5pk8XFxbKVr/2a+4lZT/c3OGoBOM1yRRA==",
- "dependencies": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/is-array-buffer": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.310.0.tgz",
- "integrity": "sha512-urnbcCR+h9NWUnmOtet/s4ghvzsidFmspfhYaHAmSRdy9yDjdjBJMFjjsn85A1ODUktztm+cVncXjQ38WCMjMQ==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/middleware-content-length": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.310.0.tgz",
- "integrity": "sha512-P8tQZxgDt6CAh1wd/W6WPzjc+uWPJwQkm+F7rAwRlM+k9q17HrhnksGDKcpuuLyIhPQYdmOMIkpKVgXGa4avhQ==",
- "dependencies": {
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/middleware-endpoint": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.310.0.tgz",
- "integrity": "sha512-Z+N2vOL8K354/lstkClxLLsr6hCpVRh+0tCMXrVj66/NtKysCEZ/0b9LmqOwD9pWHNiI2mJqXwY0gxNlKAroUg==",
- "dependencies": {
- "@aws-sdk/middleware-serde": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/url-parser": "3.310.0",
- "@aws-sdk/util-middleware": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/middleware-host-header": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.310.0.tgz",
- "integrity": "sha512-QWSA+46/hXorXyWa61ic2K7qZzwHTiwfk2e9mRRjeIRepUgI3qxFjsYqrWtrOGBjmFmq0pYIY8Bb/DCJuQqcoA==",
- "dependencies": {
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/middleware-logger": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.310.0.tgz",
- "integrity": "sha512-Lurm8XofrASBRnAVtiSNuDSRsRqPNg27RIFLLsLp/pqog9nFJ0vz0kgdb9S5Z+zw83Mm+UlqOe6D8NTUNp4fVg==",
- "dependencies": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/middleware-recursion-detection": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.310.0.tgz",
- "integrity": "sha512-SuB75/xk/gyue24gkriTwO2jFd7YcUGZDClQYuRejgbXSa3CO0lWyawQtfLcSSEBp9izrEVXuFH24K1eAft5nQ==",
- "dependencies": {
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/middleware-retry": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.310.0.tgz",
- "integrity": "sha512-oTPsRy2W4s+dfxbJPW7Km+hHtv/OMsNsVfThAq8DDYKC13qlr1aAyOqGLD+dpBy2aKe7ss517Sy2HcHtHqm7/g==",
- "dependencies": {
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/service-error-classification": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/util-middleware": "3.310.0",
- "@aws-sdk/util-retry": "3.310.0",
- "tslib": "^2.5.0",
- "uuid": "^8.3.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/middleware-sdk-sts": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.310.0.tgz",
- "integrity": "sha512-+5PFwlYNLvLLIfw0ASAoWV/iIF8Zv6R6QGtyP0CclhRSvNjgbQDVnV0g95MC5qvh+GB/Yjlkt8qAjLSPjHfsrQ==",
- "dependencies": {
- "@aws-sdk/middleware-signing": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/middleware-serde": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.310.0.tgz",
- "integrity": "sha512-RNeeTVWSLTaentUeCgQKZhAl+C6hxtwD78cQWS10UymWpQFwbaxztzKUu4UQS5xA2j6PxwPRRUjqa4jcFjfLsg==",
- "dependencies": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/middleware-signing": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.310.0.tgz",
- "integrity": "sha512-f9mKq+XMdW207Af3hKjdTnpNhdtwqWuvFs/ZyXoOkp/g1MY1O6L23Jy6i52m29LxbT4AuNRG1oKODfXM0vYVjQ==",
- "dependencies": {
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/signature-v4": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/util-middleware": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/middleware-stack": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.310.0.tgz",
- "integrity": "sha512-010O1PD+UAcZVKRvqEusE1KJqN96wwrf6QsqbRM0ywsKQ21NDweaHvEDlds2VHpgmofxkRLRu/IDrlPkKRQrRg==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/middleware-user-agent": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.310.0.tgz",
- "integrity": "sha512-x3IOwSwSbwKidlxRk3CNVHVUb06SRuaELxggCaR++QVI8NU6qD/l4VHXKVRvbTHiC/cYxXE/GaBDgQVpDR7V/g==",
- "dependencies": {
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/util-endpoints": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/node-config-provider": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.310.0.tgz",
- "integrity": "sha512-T/Pp6htc6hq/Cq+MLNDSyiwWCMVF6GqbBbXKVlO5L8rdHx4sq9xPdoPveZhGWrxvkanjA6eCwUp6E0riBOSVng==",
- "dependencies": {
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/shared-ini-file-loader": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/node-http-handler": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.310.0.tgz",
- "integrity": "sha512-irv9mbcM9xC2xYjArQF5SYmHBMu4ciMWtGsoHII1nRuFOl9FoT4ffTvEPuLlfC6pznzvKt9zvnm6xXj7gDChKg==",
- "dependencies": {
- "@aws-sdk/abort-controller": "3.310.0",
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/querystring-builder": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/property-provider": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.310.0.tgz",
- "integrity": "sha512-3lxDb0akV6BBzmFe4nLPaoliQbAifyWJhuvuDOu7e8NzouvpQXs0275w9LePhhcgjKAEVXUIse05ZW2DLbxo/g==",
- "dependencies": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/protocol-http": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.310.0.tgz",
- "integrity": "sha512-fgZ1aw/irQtnrsR58pS8ThKOWo57Py3xX6giRvwSgZDEcxHfVzuQjy9yPuV++v04fdmdtgpbGf8WfvAAJ11yXQ==",
- "dependencies": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/querystring-builder": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.310.0.tgz",
- "integrity": "sha512-ZHH8GV/80+pWGo7DzsvwvXR5xVxUHXUvPJPFAkhr6nCf78igdoF8gR10ScFoEKbtEapoNTaZlKHPXxpD8aPG7A==",
- "dependencies": {
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/util-uri-escape": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/querystring-parser": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.310.0.tgz",
- "integrity": "sha512-YkIznoP6lsiIUHinx++/lbb3tlMURGGqMpo0Pnn32zYzGrJXA6eC3D0as2EcMjo55onTfuLcIiX4qzXes2MYOA==",
- "dependencies": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/service-error-classification": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.310.0.tgz",
- "integrity": "sha512-PuyC7k3qfIKeH2LCnDwbttMOKq3qAx4buvg0yfnJtQOz6t1AR8gsnAq0CjKXXyfkXwNKWTqCpE6lVNUIkXgsMw==",
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/shared-ini-file-loader": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.310.0.tgz",
- "integrity": "sha512-N0q9pG0xSjQwc690YQND5bofm+4nfUviQ/Ppgan2kU6aU0WUq8KwgHJBto/YEEI+VlrME30jZJnxtOvcZJc2XA==",
- "dependencies": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/signature-v4": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.310.0.tgz",
- "integrity": "sha512-1M60P1ZBNAjCFv9sYW29OF6okktaeibWyW3lMXqzoHF70lHBZh+838iUchznXUA5FLabfn4jBFWMRxlAXJUY2Q==",
- "dependencies": {
- "@aws-sdk/is-array-buffer": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/util-hex-encoding": "3.310.0",
- "@aws-sdk/util-middleware": "3.310.0",
- "@aws-sdk/util-uri-escape": "3.310.0",
- "@aws-sdk/util-utf8": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/smithy-client": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.310.0.tgz",
- "integrity": "sha512-UHMFvhoB2RLzsTb0mQe1ofvBUg/+/JEu1uptavxf/hEpEKZnRAaHH5FNkTG+mbFd/olay/QFjqNcMD6t8LcsNQ==",
- "dependencies": {
- "@aws-sdk/middleware-stack": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/token-providers": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.310.0.tgz",
- "integrity": "sha512-G1JvB+2v8k900VJFkKVQXgLGF50ShOEIPxfK1gSQLkSU85vPwGIAANs1KvnlW08FsNbWp3+sKca4kfYKsooXMw==",
- "dependencies": {
- "@aws-sdk/client-sso-oidc": "3.310.0",
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/shared-ini-file-loader": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/types": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.310.0.tgz",
- "integrity": "sha512-j8eamQJ7YcIhw7fneUfs8LYl3t01k4uHi4ZDmNRgtbmbmTTG3FZc2MotStZnp3nZB6vLiPF1o5aoJxWVvkzS6A==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/url-parser": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.310.0.tgz",
- "integrity": "sha512-mCLnCaSB9rQvAgx33u0DujLvr4d5yEm/W5r789GblwwQnlNXedVu50QRizMLTpltYWyAUoXjJgQnJHmJMaKXhw==",
- "dependencies": {
- "@aws-sdk/querystring-parser": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/util-base64": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64/-/util-base64-3.310.0.tgz",
- "integrity": "sha512-v3+HBKQvqgdzcbL+pFswlx5HQsd9L6ZTlyPVL2LS9nNXnCcR3XgGz9jRskikRUuUvUXtkSG1J88GAOnJ/apTPg==",
- "dependencies": {
- "@aws-sdk/util-buffer-from": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/util-body-length-browser": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.310.0.tgz",
- "integrity": "sha512-sxsC3lPBGfpHtNTUoGXMQXLwjmR0zVpx0rSvzTPAuoVILVsp5AU/w5FphNPxD5OVIjNbZv9KsKTuvNTiZjDp9g==",
- "dependencies": {
- "tslib": "^2.5.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/util-body-length-node": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-node/-/util-body-length-node-3.310.0.tgz",
- "integrity": "sha512-2tqGXdyKhyA6w4zz7UPoS8Ip+7sayOg9BwHNidiGm2ikbDxm1YrCfYXvCBdwaJxa4hJfRVz+aL9e+d3GqPI9pQ==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/util-buffer-from": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.310.0.tgz",
- "integrity": "sha512-i6LVeXFtGih5Zs8enLrt+ExXY92QV25jtEnTKHsmlFqFAuL3VBeod6boeMXkN2p9lbSVVQ1sAOOYZOHYbYkntw==",
- "dependencies": {
- "@aws-sdk/is-array-buffer": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/util-config-provider": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-config-provider/-/util-config-provider-3.310.0.tgz",
- "integrity": "sha512-xIBaYo8dwiojCw8vnUcIL4Z5tyfb1v3yjqyJKJWV/dqKUFOOS0U591plmXbM+M/QkXyML3ypon1f8+BoaDExrg==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/util-defaults-mode-browser": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.310.0.tgz",
- "integrity": "sha512-Mr2AoQsjAYNM5oAS2YJlYJqhiCvkFV/hu48slOZgbY4G7ueW4cM0DPkR16wqjcRCGqZ4JmAZB8Q5R0DMrLjhOQ==",
- "dependencies": {
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "bowser": "^2.11.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/util-defaults-mode-node": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.310.0.tgz",
- "integrity": "sha512-JyBlvhQGR8w8NpFRZZXRVTDesafFKTu/gTWjcoxP7twa+fYHSIgPPFGnlcJ/iHaucjamSaWi5EQ+YQmnSZ8yHA==",
- "dependencies": {
- "@aws-sdk/config-resolver": "3.310.0",
- "@aws-sdk/credential-provider-imds": "3.310.0",
- "@aws-sdk/node-config-provider": "3.310.0",
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/util-endpoints": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.310.0.tgz",
- "integrity": "sha512-zG+/d/O5KPmAaeOMPd6bW1abifdT0H03f42keLjYEoRZzYtHPC5DuPE0UayiWGckI6BCDgy0sRKXCYS49UNFaQ==",
- "dependencies": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/util-hex-encoding": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.310.0.tgz",
- "integrity": "sha512-sVN7mcCCDSJ67pI1ZMtk84SKGqyix6/0A1Ab163YKn+lFBQRMKexleZzpYzNGxYzmQS6VanP/cfU7NiLQOaSfA==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/util-middleware": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.310.0.tgz",
- "integrity": "sha512-FTSUKL/eRb9X6uEZClrTe27QFXUNNp7fxYrPndZwk1hlaOP5ix+MIHBcI7pIiiY/JPfOUmPyZOu+HetlFXjWog==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/util-retry": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-retry/-/util-retry-3.310.0.tgz",
- "integrity": "sha512-FwWGhCBLfoivTMUHu1LIn4NjrN9JLJ/aX5aZmbcPIOhZVFJj638j0qDgZXyfvVqBuBZh7M8kGq0Oahy3dp69OA==",
- "dependencies": {
- "@aws-sdk/service-error-classification": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">= 14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/util-uri-escape": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.310.0.tgz",
- "integrity": "sha512-drzt+aB2qo2LgtDoiy/3sVG8w63cgLkqFIa2NFlGpUgHFWTXkqtbgf4L5QdjRGKWhmZsnqkbtL7vkSWEcYDJ4Q==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/util-user-agent-browser": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.310.0.tgz",
- "integrity": "sha512-yU/4QnHHuQ5z3vsUqMQVfYLbZGYwpYblPiuZx4Zo9+x0PBkNjYMqctdDcrpoH9Z2xZiDN16AmQGK1tix117ZKw==",
- "dependencies": {
- "@aws-sdk/types": "3.310.0",
- "bowser": "^2.11.0",
- "tslib": "^2.5.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/util-user-agent-node": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.310.0.tgz",
- "integrity": "sha512-Ra3pEl+Gn2BpeE7KiDGpi4zj7WJXZA5GXnGo3mjbi9+Y3zrbuhJAbdZO3mO/o7xDgMC6ph4xCTbaSGzU6b6EDg==",
- "dependencies": {
- "@aws-sdk/node-config-provider": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- },
- "peerDependencies": {
- "aws-crt": ">=1.0.0"
- },
- "peerDependenciesMeta": {
- "aws-crt": {
- "optional": true
- }
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/util-utf8": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8/-/util-utf8-3.310.0.tgz",
- "integrity": "sha512-DnLfFT8uCO22uOJc0pt0DsSNau1GTisngBCDw8jQuWT5CqogMJu4b/uXmwEqfj8B3GX6Xsz8zOd6JpRlPftQoA==",
- "dependencies": {
- "@aws-sdk/util-buffer-from": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-rds/node_modules/@aws-sdk/util-waiter": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-waiter/-/util-waiter-3.310.0.tgz",
- "integrity": "sha512-AV5j3guH/Y4REu+Qh3eXQU9igljHuU4XjX2sADAgf54C0kkhcCCkkiuzk3IsX089nyJCqIcj5idbjdvpnH88Vw==",
- "dependencies": {
- "@aws-sdk/abort-controller": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-sso": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.295.0.tgz",
- "integrity": "sha512-uNEchm1LAQHP2/S21jz0NxCe8yqUe3J1jZG3N/dwx7uKVndHomTmjBsClGxT8IL9hC/Xl57G+fEpTCrFMjUR2g==",
- "dependencies": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/config-resolver": "3.295.0",
- "@aws-sdk/fetch-http-handler": "3.295.0",
- "@aws-sdk/hash-node": "3.295.0",
- "@aws-sdk/invalid-dependency": "3.295.0",
- "@aws-sdk/middleware-content-length": "3.295.0",
- "@aws-sdk/middleware-endpoint": "3.295.0",
- "@aws-sdk/middleware-host-header": "3.295.0",
- "@aws-sdk/middleware-logger": "3.295.0",
- "@aws-sdk/middleware-recursion-detection": "3.295.0",
- "@aws-sdk/middleware-retry": "3.295.0",
- "@aws-sdk/middleware-serde": "3.295.0",
- "@aws-sdk/middleware-stack": "3.295.0",
- "@aws-sdk/middleware-user-agent": "3.295.0",
- "@aws-sdk/node-config-provider": "3.295.0",
- "@aws-sdk/node-http-handler": "3.295.0",
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/smithy-client": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/url-parser": "3.295.0",
- "@aws-sdk/util-base64": "3.295.0",
- "@aws-sdk/util-body-length-browser": "3.295.0",
- "@aws-sdk/util-body-length-node": "3.295.0",
- "@aws-sdk/util-defaults-mode-browser": "3.295.0",
- "@aws-sdk/util-defaults-mode-node": "3.295.0",
- "@aws-sdk/util-endpoints": "3.295.0",
- "@aws-sdk/util-retry": "3.295.0",
- "@aws-sdk/util-user-agent-browser": "3.295.0",
- "@aws-sdk/util-user-agent-node": "3.295.0",
- "@aws-sdk/util-utf8": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-sso-oidc": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.295.0.tgz",
- "integrity": "sha512-HijuG2OAmTy0Wa3JHgIMBrBlsWC6GjWkH8KcRIGbFUH2nW8LFh3gBKuB1oubZ4wAdOIBFNECWA6FKFayFlKmew==",
- "dependencies": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/config-resolver": "3.295.0",
- "@aws-sdk/fetch-http-handler": "3.295.0",
- "@aws-sdk/hash-node": "3.295.0",
- "@aws-sdk/invalid-dependency": "3.295.0",
- "@aws-sdk/middleware-content-length": "3.295.0",
- "@aws-sdk/middleware-endpoint": "3.295.0",
- "@aws-sdk/middleware-host-header": "3.295.0",
- "@aws-sdk/middleware-logger": "3.295.0",
- "@aws-sdk/middleware-recursion-detection": "3.295.0",
- "@aws-sdk/middleware-retry": "3.295.0",
- "@aws-sdk/middleware-serde": "3.295.0",
- "@aws-sdk/middleware-stack": "3.295.0",
- "@aws-sdk/middleware-user-agent": "3.295.0",
- "@aws-sdk/node-config-provider": "3.295.0",
- "@aws-sdk/node-http-handler": "3.295.0",
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/smithy-client": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/url-parser": "3.295.0",
- "@aws-sdk/util-base64": "3.295.0",
- "@aws-sdk/util-body-length-browser": "3.295.0",
- "@aws-sdk/util-body-length-node": "3.295.0",
- "@aws-sdk/util-defaults-mode-browser": "3.295.0",
- "@aws-sdk/util-defaults-mode-node": "3.295.0",
- "@aws-sdk/util-endpoints": "3.295.0",
- "@aws-sdk/util-retry": "3.295.0",
- "@aws-sdk/util-user-agent-browser": "3.295.0",
- "@aws-sdk/util-user-agent-node": "3.295.0",
- "@aws-sdk/util-utf8": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-sts": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.295.0.tgz",
- "integrity": "sha512-KrLnG5EcXvry9tmsTAONhlj60F0+Z7P2PtT0XDsS8pLayHAtd9lKXsf14DOSQa9+LbPLMFbfLbuSwvPYvgxMzg==",
- "dependencies": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/config-resolver": "3.295.0",
- "@aws-sdk/credential-provider-node": "3.295.0",
- "@aws-sdk/fetch-http-handler": "3.295.0",
- "@aws-sdk/hash-node": "3.295.0",
- "@aws-sdk/invalid-dependency": "3.295.0",
- "@aws-sdk/middleware-content-length": "3.295.0",
- "@aws-sdk/middleware-endpoint": "3.295.0",
- "@aws-sdk/middleware-host-header": "3.295.0",
- "@aws-sdk/middleware-logger": "3.295.0",
- "@aws-sdk/middleware-recursion-detection": "3.295.0",
- "@aws-sdk/middleware-retry": "3.295.0",
- "@aws-sdk/middleware-sdk-sts": "3.295.0",
- "@aws-sdk/middleware-serde": "3.295.0",
- "@aws-sdk/middleware-signing": "3.295.0",
- "@aws-sdk/middleware-stack": "3.295.0",
- "@aws-sdk/middleware-user-agent": "3.295.0",
- "@aws-sdk/node-config-provider": "3.295.0",
- "@aws-sdk/node-http-handler": "3.295.0",
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/smithy-client": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/url-parser": "3.295.0",
- "@aws-sdk/util-base64": "3.295.0",
- "@aws-sdk/util-body-length-browser": "3.295.0",
- "@aws-sdk/util-body-length-node": "3.295.0",
- "@aws-sdk/util-defaults-mode-browser": "3.295.0",
- "@aws-sdk/util-defaults-mode-node": "3.295.0",
- "@aws-sdk/util-endpoints": "3.295.0",
- "@aws-sdk/util-retry": "3.295.0",
- "@aws-sdk/util-user-agent-browser": "3.295.0",
- "@aws-sdk/util-user-agent-node": "3.295.0",
- "@aws-sdk/util-utf8": "3.295.0",
- "fast-xml-parser": "4.1.2",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/config-resolver": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.295.0.tgz",
- "integrity": "sha512-oSGdGAjmOesxGAT/Ce8P7Gdvf4KVQjasKqmlAMTXsUBxh8Mx8BQH9V3UCiCdfJ2Vx7H4pqN4Y8WcAQkje4uvbQ==",
- "dependencies": {
- "@aws-sdk/signature-v4": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/util-config-provider": "3.295.0",
- "@aws-sdk/util-middleware": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-env": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.295.0.tgz",
- "integrity": "sha512-YjUDJwhgwUgFYT4fJQVCMA1Abw2Jw1xC3EeNxeV2L54CvM9PlbFuRa5qJehePKoTLyva4bjLsMXsensXrEEIGQ==",
- "dependencies": {
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-imds": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.295.0.tgz",
- "integrity": "sha512-+tOVCZi7LUG2pvjK9P35hhXL1cZTJsbGtrMsIxrlUODjKEhht4RSiQH7zT324x6MkYby9iLjU4SUejyKBKDhYQ==",
- "dependencies": {
- "@aws-sdk/node-config-provider": "3.295.0",
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/url-parser": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-ini": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.295.0.tgz",
- "integrity": "sha512-XU3UqVVxxjyXcZ2Wkx3CM+/eLUM/EDlqJkLU6nl3FDGzPZeXC3G9Z9ZywGBo7dpRbBpDfpzSSukJisiGLTwg2w==",
- "dependencies": {
- "@aws-sdk/credential-provider-env": "3.295.0",
- "@aws-sdk/credential-provider-imds": "3.295.0",
- "@aws-sdk/credential-provider-process": "3.295.0",
- "@aws-sdk/credential-provider-sso": "3.295.0",
- "@aws-sdk/credential-provider-web-identity": "3.295.0",
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/shared-ini-file-loader": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-node": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.295.0.tgz",
- "integrity": "sha512-dU+nDJJKCyx/YBKeGgSuFM1okdoNVGWLTzrkPohPGy5+KnPaFCscrqRe2ni0ihQscguwSFXygV5SQoYNp1FGwA==",
- "dependencies": {
- "@aws-sdk/credential-provider-env": "3.295.0",
- "@aws-sdk/credential-provider-imds": "3.295.0",
- "@aws-sdk/credential-provider-ini": "3.295.0",
- "@aws-sdk/credential-provider-process": "3.295.0",
- "@aws-sdk/credential-provider-sso": "3.295.0",
- "@aws-sdk/credential-provider-web-identity": "3.295.0",
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/shared-ini-file-loader": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-process": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.295.0.tgz",
- "integrity": "sha512-efA41QAcKlb/hbDZVXnUApMPjOnu8Zj58o0WqHAdcpu7qSDzZdsmJ6dqknAbj14cyDjzXaexuN+wubGUAL9IoQ==",
- "dependencies": {
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/shared-ini-file-loader": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-sso": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.295.0.tgz",
- "integrity": "sha512-cJoCLbg3ud3/NK7otcBHkRaPvdsVEyX9tryLIPuj8rgagFWneexVh4Kzs9k+PtRN764TjVFzITw99LxBf0fe1w==",
- "dependencies": {
- "@aws-sdk/client-sso": "3.295.0",
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/shared-ini-file-loader": "3.295.0",
- "@aws-sdk/token-providers": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-web-identity": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.295.0.tgz",
- "integrity": "sha512-rBDhRYh4PiOnvz0M7AbYZZCiaPm5JDkM0xzGHEKKiW/A1wS2Gd2qbyEIK4APQ7vZMX+IJaSBBabfqm+vX5Y1kw==",
- "dependencies": {
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/endpoint-cache": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.295.0.tgz",
- "integrity": "sha512-81wVPETzx8X69ATVxwL30SV6CGtb3eO9i+ayfpopts8PHm5/1YwlBJ/KrTvdRaRKha4WAeCGIrvlKWzcl5UCCw==",
- "dependencies": {
- "mnemonist": "0.38.3",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/fetch-http-handler": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.295.0.tgz",
- "integrity": "sha512-xs274LSLeF2313dAaq7gvm/m0e0tb0/Bt2vew4Lj2zP6YNRtuNlStfSNhYHHuIkOqjTwLeAmKdK+cWFnXKQPTA==",
- "dependencies": {
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/querystring-builder": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/util-base64": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "node_modules/@aws-sdk/hash-node": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.295.0.tgz",
- "integrity": "sha512-jLq6QXUpvtYYu9+K8BECXpw7U52RBrewj/t/ALUVJsEhtwpx16K1WzMqwcVhkQ8mc/xQiki/T4eFSThODZAlcw==",
- "dependencies": {
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/util-buffer-from": "3.295.0",
- "@aws-sdk/util-utf8": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/invalid-dependency": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.295.0.tgz",
- "integrity": "sha512-ctXFKW4qnhLqZ0+qyEK1l0TOYQYwd2+vjj6wdjAiHuKoH6yIMqJ97LOT7oq3drvMQbnXa4I2jCOSFVuNSnzJ7Q==",
- "dependencies": {
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "node_modules/@aws-sdk/is-array-buffer": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.295.0.tgz",
- "integrity": "sha512-SCIt10cr5dud7hvwveU4wkLjvkGssJ3GrcbHCds2NwI+JHmpcaaNYLAqi305JAuT29T36U5ssTFDSmrrEOcfag==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-content-length": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.295.0.tgz",
- "integrity": "sha512-XzrVPuO1JwxJx5PFHP9eMZLP9zyQxPZ8PM9gTWdOgoc1BMtxCkDZ3HLOnJtcfmfbz8nwSt2/H+wlBEXaRrf7Fg==",
- "dependencies": {
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-endpoint": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.295.0.tgz",
- "integrity": "sha512-MFRW6XyZABAOeFPu2CC37h+ol6ADaKs8fqqJrv9gtNb13r6c0UeztQFwI6V3tLlZwX7zzH7HcwYFKyks5VO6Xw==",
- "dependencies": {
- "@aws-sdk/middleware-serde": "3.295.0",
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/signature-v4": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/url-parser": "3.295.0",
- "@aws-sdk/util-config-provider": "3.295.0",
- "@aws-sdk/util-middleware": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-endpoint-discovery": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.295.0.tgz",
- "integrity": "sha512-wEezLBb/PFg2Nb+KHfJimFk+kRYE9a7G5vvs8zLXFelhunJ83TG0C+aSF4S3V5hMqngtZobV2mSJq4iwYEo6Ww==",
- "dependencies": {
- "@aws-sdk/config-resolver": "3.295.0",
- "@aws-sdk/endpoint-cache": "3.295.0",
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-host-header": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.295.0.tgz",
- "integrity": "sha512-CjdC8eCILSuNHTF2AZOtFta5lMvLMM3bXBTto0LKYeHQixgBHmRSgcShfBTiWEPgIgeNSFEjMbKX6bLnHSnODg==",
- "dependencies": {
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-logger": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.295.0.tgz",
- "integrity": "sha512-dbv0VTA7Dh6ZCkmCs0U7/ssZiDtHDI7Bq3zab+RxEyLEE4wr73bW6occq579U/QQJHOZQ6EBdvYig8ntRNlzVg==",
- "dependencies": {
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-recursion-detection": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.295.0.tgz",
- "integrity": "sha512-9Wjb8Y7H0ctL8gIKtGFwXhpHb3c2UGGi2P9I+p2PJwW08rDnMlOpUItY0v49SbZ+6uct1VNBs6iJ+jkv0h5MEQ==",
- "dependencies": {
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-retry": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.295.0.tgz",
- "integrity": "sha512-IdVX86VaDSSPcGI1JJM8lffabOMmGC9TUpskKkKdFnLW6eKtFohye+hlf2h6Y/2wdvoqCdi6XZyQX9WPJHiHtw==",
- "dependencies": {
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/service-error-classification": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/util-middleware": "3.295.0",
- "@aws-sdk/util-retry": "3.295.0",
- "tslib": "^2.5.0",
- "uuid": "^8.3.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-sdk-ec2": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-ec2/-/middleware-sdk-ec2-3.295.0.tgz",
- "integrity": "sha512-XBWtECslU7WoV+CCvTPp0pzj4iBDfFYKeQNFKNp7q+t25uv2Gi+GH4a1DZ3tFAu36FRB0ZkVEk0l237rhgygtA==",
- "dependencies": {
- "@aws-sdk/middleware-endpoint": "3.295.0",
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/signature-v4": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/util-format-url": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-sdk-rds": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-rds/-/middleware-sdk-rds-3.310.0.tgz",
- "integrity": "sha512-V1nUsjggGLjy+Hx/z/7tb6bnfzZ1Kx4ikOdYVlTidnSCWZdh+kFE5Em16f5Q3erwG5Sil4Uxk0vpj+MSFP5MKA==",
- "dependencies": {
- "@aws-sdk/middleware-endpoint": "3.310.0",
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/signature-v4": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/util-format-url": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-sdk-rds/node_modules/@aws-sdk/is-array-buffer": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.310.0.tgz",
- "integrity": "sha512-urnbcCR+h9NWUnmOtet/s4ghvzsidFmspfhYaHAmSRdy9yDjdjBJMFjjsn85A1ODUktztm+cVncXjQ38WCMjMQ==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-sdk-rds/node_modules/@aws-sdk/middleware-endpoint": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.310.0.tgz",
- "integrity": "sha512-Z+N2vOL8K354/lstkClxLLsr6hCpVRh+0tCMXrVj66/NtKysCEZ/0b9LmqOwD9pWHNiI2mJqXwY0gxNlKAroUg==",
- "dependencies": {
- "@aws-sdk/middleware-serde": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/url-parser": "3.310.0",
- "@aws-sdk/util-middleware": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-sdk-rds/node_modules/@aws-sdk/middleware-serde": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.310.0.tgz",
- "integrity": "sha512-RNeeTVWSLTaentUeCgQKZhAl+C6hxtwD78cQWS10UymWpQFwbaxztzKUu4UQS5xA2j6PxwPRRUjqa4jcFjfLsg==",
- "dependencies": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-sdk-rds/node_modules/@aws-sdk/protocol-http": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.310.0.tgz",
- "integrity": "sha512-fgZ1aw/irQtnrsR58pS8ThKOWo57Py3xX6giRvwSgZDEcxHfVzuQjy9yPuV++v04fdmdtgpbGf8WfvAAJ11yXQ==",
- "dependencies": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-sdk-rds/node_modules/@aws-sdk/querystring-builder": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.310.0.tgz",
- "integrity": "sha512-ZHH8GV/80+pWGo7DzsvwvXR5xVxUHXUvPJPFAkhr6nCf78igdoF8gR10ScFoEKbtEapoNTaZlKHPXxpD8aPG7A==",
- "dependencies": {
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/util-uri-escape": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-sdk-rds/node_modules/@aws-sdk/querystring-parser": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.310.0.tgz",
- "integrity": "sha512-YkIznoP6lsiIUHinx++/lbb3tlMURGGqMpo0Pnn32zYzGrJXA6eC3D0as2EcMjo55onTfuLcIiX4qzXes2MYOA==",
- "dependencies": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-sdk-rds/node_modules/@aws-sdk/signature-v4": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.310.0.tgz",
- "integrity": "sha512-1M60P1ZBNAjCFv9sYW29OF6okktaeibWyW3lMXqzoHF70lHBZh+838iUchznXUA5FLabfn4jBFWMRxlAXJUY2Q==",
- "dependencies": {
- "@aws-sdk/is-array-buffer": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/util-hex-encoding": "3.310.0",
- "@aws-sdk/util-middleware": "3.310.0",
- "@aws-sdk/util-uri-escape": "3.310.0",
- "@aws-sdk/util-utf8": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-sdk-rds/node_modules/@aws-sdk/types": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.310.0.tgz",
- "integrity": "sha512-j8eamQJ7YcIhw7fneUfs8LYl3t01k4uHi4ZDmNRgtbmbmTTG3FZc2MotStZnp3nZB6vLiPF1o5aoJxWVvkzS6A==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-sdk-rds/node_modules/@aws-sdk/url-parser": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.310.0.tgz",
- "integrity": "sha512-mCLnCaSB9rQvAgx33u0DujLvr4d5yEm/W5r789GblwwQnlNXedVu50QRizMLTpltYWyAUoXjJgQnJHmJMaKXhw==",
- "dependencies": {
- "@aws-sdk/querystring-parser": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "node_modules/@aws-sdk/middleware-sdk-rds/node_modules/@aws-sdk/util-buffer-from": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.310.0.tgz",
- "integrity": "sha512-i6LVeXFtGih5Zs8enLrt+ExXY92QV25jtEnTKHsmlFqFAuL3VBeod6boeMXkN2p9lbSVVQ1sAOOYZOHYbYkntw==",
- "dependencies": {
- "@aws-sdk/is-array-buffer": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-sdk-rds/node_modules/@aws-sdk/util-format-url": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.310.0.tgz",
- "integrity": "sha512-NBOvmvvVR3ydquHmznfgtakiSgDhq8Ww6fq8TUaEjM+Es6+iqY4AwZo0rZ9xTX3GpCcoZy391HUi6kiXRAFzuA==",
- "dependencies": {
- "@aws-sdk/querystring-builder": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-sdk-rds/node_modules/@aws-sdk/util-hex-encoding": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.310.0.tgz",
- "integrity": "sha512-sVN7mcCCDSJ67pI1ZMtk84SKGqyix6/0A1Ab163YKn+lFBQRMKexleZzpYzNGxYzmQS6VanP/cfU7NiLQOaSfA==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-sdk-rds/node_modules/@aws-sdk/util-middleware": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.310.0.tgz",
- "integrity": "sha512-FTSUKL/eRb9X6uEZClrTe27QFXUNNp7fxYrPndZwk1hlaOP5ix+MIHBcI7pIiiY/JPfOUmPyZOu+HetlFXjWog==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-sdk-rds/node_modules/@aws-sdk/util-uri-escape": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.310.0.tgz",
- "integrity": "sha512-drzt+aB2qo2LgtDoiy/3sVG8w63cgLkqFIa2NFlGpUgHFWTXkqtbgf4L5QdjRGKWhmZsnqkbtL7vkSWEcYDJ4Q==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-sdk-rds/node_modules/@aws-sdk/util-utf8": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8/-/util-utf8-3.310.0.tgz",
- "integrity": "sha512-DnLfFT8uCO22uOJc0pt0DsSNau1GTisngBCDw8jQuWT5CqogMJu4b/uXmwEqfj8B3GX6Xsz8zOd6JpRlPftQoA==",
- "dependencies": {
- "@aws-sdk/util-buffer-from": "3.310.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-sdk-sts": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.295.0.tgz",
- "integrity": "sha512-QTHR+ZXAmii8XsbdRrqJWn6LVeGiRcFfGlniIb1YEjw1p2FU5kpayq8N1SLLtj3JWmE61Bpn0J+LAQmfjbCqFA==",
- "dependencies": {
- "@aws-sdk/middleware-signing": "3.295.0",
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/signature-v4": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-serde": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.295.0.tgz",
- "integrity": "sha512-LAKtKNKdu6Si7rmLatAq87LSa27mR6HUZ7tZHD2E4SQWOoNpS4ikKfUfATkbjC2GOfbrBYmFmQgBvpghYYZ3jw==",
- "dependencies": {
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-signing": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.295.0.tgz",
- "integrity": "sha512-LcNzGqtpo9sdWJ9mKtgjragncbin/Ynbz/pklH/HcIIi45w8ZVrhLBpW1iQZ0MBKyDacAAeWtXxKHy55DkHlvg==",
- "dependencies": {
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/signature-v4": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/util-middleware": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-stack": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.295.0.tgz",
- "integrity": "sha512-65HahosleRbpNgu6/XkABcrBmZHudRYTNpyKRfSY18QPKVQv3PRgRqv/goHrc6DHo8cxAliBoMciN88Ali1ufQ==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-user-agent": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.295.0.tgz",
- "integrity": "sha512-11MGXHFxmXgQx6aAFshLqHm3US7awXMP1Hq3IAu6j+GXSdkpkIojh/LlzRbSUftAhh23C5oQpgOkqs6fox4xCw==",
- "dependencies": {
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/util-endpoints": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/node-config-provider": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.295.0.tgz",
- "integrity": "sha512-6lkCmPMmXn6CF1qQHkE/Ii88ge/Mz9MWX+Krj3ICdBRwdMqm4LGzc9qG+bJeqbVI3tPO3djmL+b4SW4a3pvKsw==",
- "dependencies": {
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/shared-ini-file-loader": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/node-http-handler": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.295.0.tgz",
- "integrity": "sha512-Ga3vp/IY3LgzTdlSTAcxncYebE0lpQAdgxnko+z1i67OaI8DqNlTL8vdYBoHDaFOb9E6ErShLytVoHAEuJ5TpA==",
- "dependencies": {
- "@aws-sdk/abort-controller": "3.295.0",
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/querystring-builder": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/property-provider": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.295.0.tgz",
- "integrity": "sha512-5hxI1W36JWugYaBng7hKH2IxDtNohk0KMsz6wgyHVxTcsrO9VohlYa+5rHntmt3SbQAyy7n5ft9/vb1Nb5TGCw==",
- "dependencies": {
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/protocol-http": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.295.0.tgz",
- "integrity": "sha512-mDl1jfNDtOFXKQrkiTY0dbTwC9LLjmmAmE8TpxXC1v6JbOihVrARiyPdumZWP4J/71YAim1ASS6JlQHw/GuAqg==",
- "dependencies": {
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/querystring-builder": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.295.0.tgz",
- "integrity": "sha512-zgFb2pSkxOCHVusZpPjQVIwmQZf59MQEYJETk42OKaigItGTHjap9DrFzKo6+SrHeyEpJLxlZKSz5up4Hulwdw==",
- "dependencies": {
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/util-uri-escape": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/querystring-parser": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.295.0.tgz",
- "integrity": "sha512-bcm8IBHmflH1e6EHznScJbfvAmNZqwZtC6QaynNk6no/YYKr5Swm+GHqxurKBm86qCYIOoSvdoq8tyhUjXnh4Q==",
- "dependencies": {
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/service-error-classification": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.295.0.tgz",
- "integrity": "sha512-zqGxXkZUxPD7E0FJXKHZLuJwr02zg/Ux4d+elT/MUTYT9eKupmG2S5586/hZdjUxGGA7gmMMJr92mjrLVJUAkQ==",
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/shared-ini-file-loader": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.295.0.tgz",
- "integrity": "sha512-LF9+jk37/VPoIyadeb+Ls0Tqda6dauo3uG7FDfg7qdiOpdyNRuFaIZE//MTSG5mk4ExAwjkFsnslZaw31hbbUw==",
- "dependencies": {
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/signature-v4": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.295.0.tgz",
- "integrity": "sha512-yS00sIwWEnPB4aHZWJZpXVL2/wbwrymxbPZw/Xq0JXbR9+RXhzENBqw7C3d7E11K1xLnoTYlVqcJhNuNXgyeZg==",
- "dependencies": {
- "@aws-sdk/is-array-buffer": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/util-hex-encoding": "3.295.0",
- "@aws-sdk/util-middleware": "3.295.0",
- "@aws-sdk/util-uri-escape": "3.295.0",
- "@aws-sdk/util-utf8": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/smithy-client": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.295.0.tgz",
- "integrity": "sha512-6Ifq+szMeX6MjWkEEiXvQGm7moY5Wt6WfFi+dMLkZmPdOEWYB0Cr0EBpY605WHWGz702CpFLvM/z6rUkvtak5g==",
- "dependencies": {
- "@aws-sdk/middleware-stack": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/token-providers": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.295.0.tgz",
- "integrity": "sha512-/6PsplDacgBoQxFBbKYMW9ZlEeTHHdAm+xE6V+qjEsc0YXy32LwuFllfihryXLjWftrC3kr8EiehLU6d+9JaKA==",
- "dependencies": {
- "@aws-sdk/client-sso-oidc": "3.295.0",
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/shared-ini-file-loader": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/types": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.295.0.tgz",
- "integrity": "sha512-flwibucy5+PshdFLeMCClMqV3eFmjUDhcLkEUeQvVgyhGxJPIrU3ntGAfqz27bvk47ZVX5TUdCG5JdxuUaRO+A==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/url-parser": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.295.0.tgz",
- "integrity": "sha512-hev5gbi+EWHLaFNgVpoNeNTaJpqfa9ev0SvqgvCPqGlIdUnt3cP9t1Mc8jvx2kUk8ebPtrrq6cp8ZslfxoFeVA==",
- "dependencies": {
- "@aws-sdk/querystring-parser": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "node_modules/@aws-sdk/util-base64": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64/-/util-base64-3.295.0.tgz",
- "integrity": "sha512-z1r40BsBiOTALnzASvLb4qutGwPpL+jH2UKTCV5WJLXZFMzRnpZaRfeZGE8lMJ/i0+jv9H9G1FmVzE8UgB4rhw==",
- "dependencies": {
- "@aws-sdk/util-buffer-from": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/util-body-length-browser": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.295.0.tgz",
- "integrity": "sha512-NbG4/RSHV1VueStPRclSo5zRjNUmcDlNAs29sniZF+YaN0+Ad7hEdu/YgJw39shBfUaurz2Wv0pufU3cxE5Tng==",
- "dependencies": {
- "tslib": "^2.5.0"
- }
- },
- "node_modules/@aws-sdk/util-body-length-node": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-node/-/util-body-length-node-3.295.0.tgz",
- "integrity": "sha512-dvGf8VBmrT66lM0n6P/h7wnlHS4Atafyivyl8f4TUCMvRdpqryvvrtnX6yYcq3T7VKQmas/2SOlgDvcrhGXaiw==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/util-buffer-from": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.295.0.tgz",
- "integrity": "sha512-5ezVEITQnrQKn+CU9qfZHgRp2nrrbX0Clmlm9aiNjAEQEPHY33tWl0t6n8h8yU+IpGiNRMWBVC4aSJaE5NA1mA==",
- "dependencies": {
- "@aws-sdk/is-array-buffer": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/util-config-provider": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-config-provider/-/util-config-provider-3.295.0.tgz",
- "integrity": "sha512-/5Dl1aV2yI8YQjqwmg4RTnl/E9NmNsx7HIwBZt+dTcOrM0LMUwczQBFFcLyqCj/qv5y+VsvLoAAA/OiBT7hb3w==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/util-defaults-mode-browser": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.295.0.tgz",
- "integrity": "sha512-QqVyl4Sxi9Umn2+TdhZR8fHQRWWs2361JCylig1GzH+ud+8jinDS6tLtWxhzrea2XdKGb4xqjTC4AhCuBqgSmA==",
- "dependencies": {
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "bowser": "^2.11.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/@aws-sdk/util-defaults-mode-node": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.295.0.tgz",
- "integrity": "sha512-R1e94v6HMsUec8/P2tJmab5fYsT9X3+Kh1rMzCEA27V+kAD88eKStzE26Yb1kQDAC+Fg3Fe1KS1bg4dmQKUSVg==",
- "dependencies": {
- "@aws-sdk/config-resolver": "3.295.0",
- "@aws-sdk/credential-provider-imds": "3.295.0",
- "@aws-sdk/node-config-provider": "3.295.0",
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/@aws-sdk/util-endpoints": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.295.0.tgz",
- "integrity": "sha512-WZR6jAD++7Wb6ER1SM/U82xU+OVWihcc8V90AzTWyDb0JPeKuogwWokV1aHXiGaQGbWULr1wY1R3wthhvEs3Bg==",
- "dependencies": {
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/util-format-url": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.295.0.tgz",
- "integrity": "sha512-sONC9XCz6jtib1Ydh1EfEfKZR2/KZVdHv/KUx8VosPzMEnh6+maqfrdeHN6qQZJNdK/na2ZOIhONMDVCRktT9w==",
- "dependencies": {
- "@aws-sdk/querystring-builder": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/util-hex-encoding": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.295.0.tgz",
- "integrity": "sha512-XJcoVo41kHzhe28PBm/rqt5mdCp8R6abwiW9ug1dA6FOoPUO8kBUxDv6xaOmA2hfRvd2ocFfBXaUCBqUowkGcQ==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/util-locate-window": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.295.0.tgz",
- "integrity": "sha512-d/s+zhUx5Kh4l/ecMP/TBjzp1GR/g89Q4nWH6+wH5WgdHsK+LG+vmsk6mVNuP/8wsCofYG4NBqp5Ulbztbm9QA==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/util-middleware": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.295.0.tgz",
- "integrity": "sha512-t6UdduLHV97IRZmd1YA0v5HCwerz+OXxDF8lLK0G7qihde0jv6tq5w8fTTjgehDFKM0UGUiaahOtjEcRK7F2Aw==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/util-retry": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-retry/-/util-retry-3.295.0.tgz",
- "integrity": "sha512-3xp3A5XtPWGsN9aLuzM3mB4hpM3nZJ5JJiGFgUXu/CTP2ahipbVbMwtRpIUjYDh1kvdjoaDJatEVJ7JhJrXFew==",
- "dependencies": {
- "@aws-sdk/service-error-classification": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">= 14.0.0"
- }
- },
- "node_modules/@aws-sdk/util-uri-escape": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.295.0.tgz",
- "integrity": "sha512-1H5DcyIoXF8XcPBWf7wzHt0l+TW2EoR8Oq4gsVrPTQkHMTVclC2Yn8EF3gc4arwVBzwLulI9LMBE2L8fexGfTQ==",
- "dependencies": {
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/util-user-agent-browser": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.295.0.tgz",
- "integrity": "sha512-lSU80r6yMwSDLkBZ0900G/kHLz/QgXewPXz56Xnq7NHWu7YliY6fzT1zWHPRGwcfCctTGMTWw+10ZSu/0Xv9nw==",
- "dependencies": {
- "@aws-sdk/types": "3.295.0",
- "bowser": "^2.11.0",
- "tslib": "^2.5.0"
- }
- },
- "node_modules/@aws-sdk/util-user-agent-node": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.295.0.tgz",
- "integrity": "sha512-EVt/4nWTYLbS6llhjE4sn2tn1mBlifyK6ezAse5kr6boNG3dJt6Y7gHAXXglkmblw2bflxqgOaKj5YCcZFUSyQ==",
- "dependencies": {
- "@aws-sdk/node-config-provider": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- },
- "peerDependencies": {
- "aws-crt": ">=1.0.0"
- },
- "peerDependenciesMeta": {
- "aws-crt": {
- "optional": true
- }
- }
- },
- "node_modules/@aws-sdk/util-utf8": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8/-/util-utf8-3.295.0.tgz",
- "integrity": "sha512-ITN8v3F63ZkA4sdmCtSbS/mhav4F0MEAiXDAUXtMJLNqVtaVcyQST4i9vNmPpIVthAPAtP0QjyF2tq/Di8bxtQ==",
- "dependencies": {
- "@aws-sdk/util-buffer-from": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/util-utf8-browser": {
- "version": "3.259.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz",
- "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==",
- "dependencies": {
- "tslib": "^2.3.1"
- }
- },
- "node_modules/@aws-sdk/util-waiter": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-waiter/-/util-waiter-3.295.0.tgz",
- "integrity": "sha512-7FHJhSqfBSGsbNUtXyJvu0cnKCtVoQ1HtVZ2OWvW9V0Vyi++ifm6UFvHecrQPocfXu4WoOEhWktZ78iUdCA/MA==",
- "dependencies": {
- "@aws-sdk/abort-controller": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-solutions-constructs/aws-lambda-dynamodb": {
- "version": "2.30.0",
- "resolved": "https://registry.npmjs.org/@aws-solutions-constructs/aws-lambda-dynamodb/-/aws-lambda-dynamodb-2.30.0.tgz",
- "integrity": "sha512-Agh1RNZI3qhIJuPOdCMzv8RzBZZH8NdfMsYkiVvn4hEB/h4/arFfeArxL5z8SlJbvFwK2Dg08L2UXdtJSlH6AA==",
- "dependencies": {
- "@aws-solutions-constructs/core": "2.30.0"
- },
- "peerDependencies": {
- "@aws-solutions-constructs/core": "2.30.0",
- "aws-cdk-lib": "^2.57.0",
- "constructs": "^10.0.0"
- }
- },
- "node_modules/@aws-solutions-constructs/core": {
- "version": "2.30.0",
- "resolved": "https://registry.npmjs.org/@aws-solutions-constructs/core/-/core-2.30.0.tgz",
- "integrity": "sha512-0sSifWV7QnQIuVlXK5LXDqYt/U7tWNHOpNsfWTivQ6fmPojhjprLmFkgIa/G3+CxWXDSaWUgUFzyhLcT72xt0Q==",
- "bundleDependencies": [
- "deepmerge",
- "npmlog",
- "deep-diff"
- ],
- "dependencies": {
- "deep-diff": "^1.0.2",
- "deepmerge": "^4.0.0",
- "npmlog": "^4.1.2"
- },
- "peerDependencies": {
- "aws-cdk-lib": "^2.57.0",
- "constructs": "^10.0.0"
- }
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/ansi-regex": {
- "version": "2.1.1",
- "inBundle": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/aproba": {
- "version": "1.2.0",
- "inBundle": true,
- "license": "ISC"
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/are-we-there-yet": {
- "version": "1.1.7",
- "inBundle": true,
- "license": "ISC",
- "dependencies": {
- "delegates": "^1.0.0",
- "readable-stream": "^2.0.6"
- }
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/code-point-at": {
- "version": "1.1.0",
- "inBundle": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/console-control-strings": {
- "version": "1.1.0",
- "inBundle": true,
- "license": "ISC"
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/core-util-is": {
- "version": "1.0.3",
- "inBundle": true,
- "license": "MIT"
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/deep-diff": {
- "version": "1.0.2",
- "inBundle": true,
- "license": "MIT"
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/deepmerge": {
- "version": "4.2.2",
- "inBundle": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/delegates": {
- "version": "1.0.0",
- "inBundle": true,
- "license": "MIT"
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/emoji-regex": {
- "version": "8.0.0",
- "inBundle": true,
- "license": "MIT"
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/gauge": {
- "version": "2.7.4",
- "inBundle": true,
- "license": "ISC",
- "dependencies": {
- "aproba": "^1.0.3",
- "console-control-strings": "^1.0.0",
- "has-unicode": "^2.0.0",
- "object-assign": "^4.1.0",
- "signal-exit": "^3.0.0",
- "string-width": "^1.0.1",
- "strip-ansi": "^3.0.1",
- "wide-align": "^1.1.0"
- }
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/has-unicode": {
- "version": "2.0.1",
- "inBundle": true,
- "license": "ISC"
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/inherits": {
- "version": "2.0.4",
- "inBundle": true,
- "license": "ISC"
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/is-fullwidth-code-point": {
- "version": "1.0.0",
- "inBundle": true,
- "license": "MIT",
- "dependencies": {
- "number-is-nan": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/isarray": {
- "version": "1.0.0",
- "inBundle": true,
- "license": "MIT"
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/npmlog": {
- "version": "4.1.2",
- "inBundle": true,
- "license": "ISC",
- "dependencies": {
- "are-we-there-yet": "~1.1.2",
- "console-control-strings": "~1.1.0",
- "gauge": "~2.7.3",
- "set-blocking": "~2.0.0"
- }
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/number-is-nan": {
- "version": "1.0.1",
- "inBundle": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/object-assign": {
- "version": "4.1.1",
- "inBundle": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/process-nextick-args": {
- "version": "2.0.1",
- "inBundle": true,
- "license": "MIT"
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/readable-stream": {
- "version": "2.3.7",
- "inBundle": true,
- "license": "MIT",
- "dependencies": {
- "core-util-is": "~1.0.0",
- "inherits": "~2.0.3",
- "isarray": "~1.0.0",
- "process-nextick-args": "~2.0.0",
- "safe-buffer": "~5.1.1",
- "string_decoder": "~1.1.1",
- "util-deprecate": "~1.0.1"
- }
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/safe-buffer": {
- "version": "5.1.2",
- "inBundle": true,
- "license": "MIT"
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/set-blocking": {
- "version": "2.0.0",
- "inBundle": true,
- "license": "ISC"
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/signal-exit": {
- "version": "3.0.7",
- "inBundle": true,
- "license": "ISC"
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/string_decoder": {
- "version": "1.1.1",
- "inBundle": true,
- "license": "MIT",
- "dependencies": {
- "safe-buffer": "~5.1.0"
- }
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/string-width": {
- "version": "1.0.2",
- "inBundle": true,
- "license": "MIT",
- "dependencies": {
- "code-point-at": "^1.0.0",
- "is-fullwidth-code-point": "^1.0.0",
- "strip-ansi": "^3.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/strip-ansi": {
- "version": "3.0.1",
- "inBundle": true,
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/util-deprecate": {
- "version": "1.0.2",
- "inBundle": true,
- "license": "MIT"
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/wide-align": {
- "version": "1.1.5",
- "inBundle": true,
- "license": "ISC",
- "dependencies": {
- "string-width": "^1.0.2 || 2 || 3 || 4"
- }
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/wide-align/node_modules/ansi-regex": {
- "version": "5.0.1",
- "inBundle": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/wide-align/node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "inBundle": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/wide-align/node_modules/string-width": {
- "version": "4.2.3",
- "inBundle": true,
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@aws-solutions-constructs/core/node_modules/wide-align/node_modules/strip-ansi": {
- "version": "6.0.1",
- "inBundle": true,
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@babel/code-frame": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
- "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==",
- "dev": true,
- "dependencies": {
- "@babel/highlight": "^7.18.6"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/compat-data": {
- "version": "7.20.10",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.10.tgz",
- "integrity": "sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/core": {
- "version": "7.20.12",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz",
- "integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==",
- "dev": true,
- "dependencies": {
- "@ampproject/remapping": "^2.1.0",
- "@babel/code-frame": "^7.18.6",
- "@babel/generator": "^7.20.7",
- "@babel/helper-compilation-targets": "^7.20.7",
- "@babel/helper-module-transforms": "^7.20.11",
- "@babel/helpers": "^7.20.7",
- "@babel/parser": "^7.20.7",
- "@babel/template": "^7.20.7",
- "@babel/traverse": "^7.20.12",
- "@babel/types": "^7.20.7",
- "convert-source-map": "^1.7.0",
- "debug": "^4.1.0",
- "gensync": "^1.0.0-beta.2",
- "json5": "^2.2.2",
- "semver": "^6.3.0"
- },
- "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.20.7",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.7.tgz",
- "integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.20.7",
- "@jridgewell/gen-mapping": "^0.3.2",
- "jsesc": "^2.5.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
- "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
- "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/@babel/helper-compilation-targets": {
- "version": "7.20.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz",
- "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==",
- "dev": true,
- "dependencies": {
- "@babel/compat-data": "^7.20.5",
- "@babel/helper-validator-option": "^7.18.6",
- "browserslist": "^4.21.3",
- "lru-cache": "^5.1.1",
- "semver": "^6.3.0"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-environment-visitor": {
- "version": "7.18.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz",
- "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-function-name": {
- "version": "7.19.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz",
- "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==",
- "dev": true,
- "dependencies": {
- "@babel/template": "^7.18.10",
- "@babel/types": "^7.19.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-hoist-variables": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz",
- "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.18.6"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-imports": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz",
- "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.18.6"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-transforms": {
- "version": "7.20.11",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz",
- "integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-environment-visitor": "^7.18.9",
- "@babel/helper-module-imports": "^7.18.6",
- "@babel/helper-simple-access": "^7.20.2",
- "@babel/helper-split-export-declaration": "^7.18.6",
- "@babel/helper-validator-identifier": "^7.19.1",
- "@babel/template": "^7.20.7",
- "@babel/traverse": "^7.20.10",
- "@babel/types": "^7.20.7"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-plugin-utils": {
- "version": "7.20.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz",
- "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-simple-access": {
- "version": "7.20.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz",
- "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.20.2"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-split-export-declaration": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz",
- "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.18.6"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-string-parser": {
- "version": "7.19.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz",
- "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-identifier": {
- "version": "7.19.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
- "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-option": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz",
- "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helpers": {
- "version": "7.20.7",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.7.tgz",
- "integrity": "sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA==",
- "dev": true,
- "dependencies": {
- "@babel/template": "^7.20.7",
- "@babel/traverse": "^7.20.7",
- "@babel/types": "^7.20.7"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/highlight": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
- "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
- "dev": true,
- "dependencies": {
- "@babel/helper-validator-identifier": "^7.18.6",
- "chalk": "^2.0.0",
- "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.20.7",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz",
- "integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==",
- "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.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz",
- "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.18.6"
- },
- "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.20.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz",
- "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.19.0"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/template": {
- "version": "7.20.7",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz",
- "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==",
- "dev": true,
- "dependencies": {
- "@babel/code-frame": "^7.18.6",
- "@babel/parser": "^7.20.7",
- "@babel/types": "^7.20.7"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/traverse": {
- "version": "7.20.12",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.12.tgz",
- "integrity": "sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ==",
- "dev": true,
- "dependencies": {
- "@babel/code-frame": "^7.18.6",
- "@babel/generator": "^7.20.7",
- "@babel/helper-environment-visitor": "^7.18.9",
- "@babel/helper-function-name": "^7.19.0",
- "@babel/helper-hoist-variables": "^7.18.6",
- "@babel/helper-split-export-declaration": "^7.18.6",
- "@babel/parser": "^7.20.7",
- "@babel/types": "^7.20.7",
- "debug": "^4.1.0",
- "globals": "^11.1.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/types": {
- "version": "7.20.7",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz",
- "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-string-parser": "^7.19.4",
- "@babel/helper-validator-identifier": "^7.19.1",
- "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/@cspotcode/source-map-support": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
- "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
- "dev": true,
- "dependencies": {
- "@jridgewell/trace-mapping": "0.3.9"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.9",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
- "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
- "dev": true,
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.0.3",
- "@jridgewell/sourcemap-codec": "^1.4.10"
- }
- },
- "node_modules/@eslint-community/eslint-utils": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
- "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
- "dev": true,
- "dependencies": {
- "eslint-visitor-keys": "^3.3.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "peerDependencies": {
- "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
- }
- },
- "node_modules/@eslint-community/regexpp": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.1.tgz",
- "integrity": "sha512-BISJ6ZE4xQsuL/FmsyRaiffpq977bMlsKfGHTQrOGFErfByxIe6iZTxPf/00Zon9b9a7iUykfQwejN3s2ZW/Bw==",
- "dev": true,
- "engines": {
- "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
- }
- },
- "node_modules/@eslint/eslintrc": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz",
- "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==",
- "dev": true,
- "dependencies": {
- "ajv": "^6.12.4",
- "debug": "^4.3.2",
- "espree": "^9.5.0",
- "globals": "^13.19.0",
- "ignore": "^5.2.0",
- "import-fresh": "^3.2.1",
- "js-yaml": "^4.1.0",
- "minimatch": "^3.1.2",
- "strip-json-comments": "^3.1.1"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/@eslint/eslintrc/node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true
- },
- "node_modules/@eslint/eslintrc/node_modules/globals": {
- "version": "13.20.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
- "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
- "dev": true,
- "dependencies": {
- "type-fest": "^0.20.2"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@eslint/eslintrc/node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
- "dev": true,
- "dependencies": {
- "argparse": "^2.0.1"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
- "node_modules/@eslint/eslintrc/node_modules/type-fest": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
- "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@eslint/js": {
- "version": "8.36.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz",
- "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==",
- "dev": true,
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- }
- },
- "node_modules/@humanwhocodes/config-array": {
- "version": "0.11.8",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
- "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==",
- "dev": true,
- "dependencies": {
- "@humanwhocodes/object-schema": "^1.2.1",
- "debug": "^4.1.1",
- "minimatch": "^3.0.5"
- },
- "engines": {
- "node": ">=10.10.0"
- }
- },
- "node_modules/@humanwhocodes/module-importer": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
- "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
- "dev": true,
- "engines": {
- "node": ">=12.22"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/nzakas"
- }
- },
- "node_modules/@humanwhocodes/object-schema": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
- "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
- "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.3.1",
- "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.3.1.tgz",
- "integrity": "sha512-IRE6GD47KwcqA09RIWrabKdHPiKDGgtAL31xDxbi/RjQMsr+lY+ppxmHwY0dUEV3qvvxZzoe5Hl0RXZJOjQNUg==",
- "dev": true,
- "dependencies": {
- "@jest/types": "^29.3.1",
- "@types/node": "*",
- "chalk": "^4.0.0",
- "jest-message-util": "^29.3.1",
- "jest-util": "^29.3.1",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/@jest/core": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.3.1.tgz",
- "integrity": "sha512-0ohVjjRex985w5MmO5L3u5GR1O30DexhBSpuwx2P+9ftyqHdJXnk7IUWiP80oHMvt7ubHCJHxV0a0vlKVuZirw==",
- "dev": true,
- "dependencies": {
- "@jest/console": "^29.3.1",
- "@jest/reporters": "^29.3.1",
- "@jest/test-result": "^29.3.1",
- "@jest/transform": "^29.3.1",
- "@jest/types": "^29.3.1",
- "@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.2.0",
- "jest-config": "^29.3.1",
- "jest-haste-map": "^29.3.1",
- "jest-message-util": "^29.3.1",
- "jest-regex-util": "^29.2.0",
- "jest-resolve": "^29.3.1",
- "jest-resolve-dependencies": "^29.3.1",
- "jest-runner": "^29.3.1",
- "jest-runtime": "^29.3.1",
- "jest-snapshot": "^29.3.1",
- "jest-util": "^29.3.1",
- "jest-validate": "^29.3.1",
- "jest-watcher": "^29.3.1",
- "micromatch": "^4.0.4",
- "pretty-format": "^29.3.1",
- "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/core/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/@jest/core/node_modules/pretty-format": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz",
- "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==",
- "dev": true,
- "dependencies": {
- "@jest/schemas": "^29.0.0",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/@jest/core/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/@jest/environment": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.3.1.tgz",
- "integrity": "sha512-pMmvfOPmoa1c1QpfFW0nXYtNLpofqo4BrCIk6f2kW4JFeNlHV2t3vd+3iDLf31e2ot2Mec0uqZfmI+U0K2CFag==",
- "dev": true,
- "dependencies": {
- "@jest/fake-timers": "^29.3.1",
- "@jest/types": "^29.3.1",
- "@types/node": "*",
- "jest-mock": "^29.3.1"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/@jest/expect": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.3.1.tgz",
- "integrity": "sha512-QivM7GlSHSsIAWzgfyP8dgeExPRZ9BIe2LsdPyEhCGkZkoyA+kGsoIzbKAfZCvvRzfZioKwPtCZIt5SaoxYCvg==",
- "dev": true,
- "dependencies": {
- "expect": "^29.3.1",
- "jest-snapshot": "^29.3.1"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/@jest/expect-utils": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.3.1.tgz",
- "integrity": "sha512-wlrznINZI5sMjwvUoLVk617ll/UYfGIZNxmbU+Pa7wmkL4vYzhV9R2pwVqUh4NWWuLQWkI8+8mOkxs//prKQ3g==",
- "dev": true,
- "dependencies": {
- "jest-get-type": "^29.2.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/@jest/fake-timers": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.3.1.tgz",
- "integrity": "sha512-iHTL/XpnDlFki9Tq0Q1GGuVeQ8BHZGIYsvCO5eN/O/oJaRzofG9Xndd9HuSDBI/0ZS79pg0iwn07OMTQ7ngF2A==",
- "dev": true,
- "dependencies": {
- "@jest/types": "^29.3.1",
- "@sinonjs/fake-timers": "^9.1.2",
- "@types/node": "*",
- "jest-message-util": "^29.3.1",
- "jest-mock": "^29.3.1",
- "jest-util": "^29.3.1"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/@jest/globals": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.3.1.tgz",
- "integrity": "sha512-cTicd134vOcwO59OPaB6AmdHQMCtWOe+/DitpTZVxWgMJ+YvXL1HNAmPyiGbSHmF/mXVBkvlm8YYtQhyHPnV6Q==",
- "dev": true,
- "dependencies": {
- "@jest/environment": "^29.3.1",
- "@jest/expect": "^29.3.1",
- "@jest/types": "^29.3.1",
- "jest-mock": "^29.3.1"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/@jest/reporters": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.3.1.tgz",
- "integrity": "sha512-GhBu3YFuDrcAYW/UESz1JphEAbvUjaY2vShRZRoRY1mxpCMB3yGSJ4j9n0GxVlEOdCf7qjvUfBCrTUUqhVfbRA==",
- "dev": true,
- "dependencies": {
- "@bcoe/v8-coverage": "^0.2.3",
- "@jest/console": "^29.3.1",
- "@jest/test-result": "^29.3.1",
- "@jest/transform": "^29.3.1",
- "@jest/types": "^29.3.1",
- "@jridgewell/trace-mapping": "^0.3.15",
- "@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": "^5.1.0",
- "istanbul-lib-report": "^3.0.0",
- "istanbul-lib-source-maps": "^4.0.0",
- "istanbul-reports": "^3.1.3",
- "jest-message-util": "^29.3.1",
- "jest-util": "^29.3.1",
- "jest-worker": "^29.3.1",
- "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.4.3",
- "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz",
- "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==",
- "dev": true,
- "dependencies": {
- "@sinclair/typebox": "^0.25.16"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/@jest/source-map": {
- "version": "29.2.0",
- "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.2.0.tgz",
- "integrity": "sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ==",
- "dev": true,
- "dependencies": {
- "@jridgewell/trace-mapping": "^0.3.15",
- "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.3.1",
- "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.3.1.tgz",
- "integrity": "sha512-qeLa6qc0ddB0kuOZyZIhfN5q0e2htngokyTWsGriedsDhItisW7SDYZ7ceOe57Ii03sL988/03wAcBh3TChMGw==",
- "dev": true,
- "dependencies": {
- "@jest/console": "^29.3.1",
- "@jest/types": "^29.3.1",
- "@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.3.1",
- "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.3.1.tgz",
- "integrity": "sha512-IqYvLbieTv20ArgKoAMyhLHNrVHJfzO6ARZAbQRlY4UGWfdDnLlZEF0BvKOMd77uIiIjSZRwq3Jb3Fa3I8+2UA==",
- "dev": true,
- "dependencies": {
- "@jest/test-result": "^29.3.1",
- "graceful-fs": "^4.2.9",
- "jest-haste-map": "^29.3.1",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/@jest/transform": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.3.1.tgz",
- "integrity": "sha512-8wmCFBTVGYqFNLWfcOWoVuMuKYPUBTnTMDkdvFtAYELwDOl9RGwOsvQWGPFxDJ8AWY9xM/8xCXdqmPK3+Q5Lug==",
- "dev": true,
- "dependencies": {
- "@babel/core": "^7.11.6",
- "@jest/types": "^29.3.1",
- "@jridgewell/trace-mapping": "^0.3.15",
- "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.3.1",
- "jest-regex-util": "^29.2.0",
- "jest-util": "^29.3.1",
- "micromatch": "^4.0.4",
- "pirates": "^4.0.4",
- "slash": "^3.0.0",
- "write-file-atomic": "^4.0.1"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/@jest/types": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.3.1.tgz",
- "integrity": "sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA==",
- "dev": true,
- "dependencies": {
- "@jest/schemas": "^29.0.0",
- "@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.1.1",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
- "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==",
- "dev": true,
- "dependencies": {
- "@jridgewell/set-array": "^1.0.0",
- "@jridgewell/sourcemap-codec": "^1.4.10"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
- "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
- "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.14",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
- "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
- "dev": true
- },
- "node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.17",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
- "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
- "dev": true,
- "dependencies": {
- "@jridgewell/resolve-uri": "3.1.0",
- "@jridgewell/sourcemap-codec": "1.4.14"
- }
- },
- "node_modules/@nodelib/fs.scandir": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
- "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.stat": "2.0.5",
- "run-parallel": "^1.1.9"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.stat": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
- "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
- "dev": true,
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.walk": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
- "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.scandir": "2.1.5",
- "fastq": "^1.6.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@sinclair/typebox": {
- "version": "0.25.24",
- "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz",
- "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==",
- "dev": true
- },
- "node_modules/@sinonjs/commons": {
- "version": "1.8.6",
- "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz",
- "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==",
- "dev": true,
- "dependencies": {
- "type-detect": "4.0.8"
- }
- },
- "node_modules/@sinonjs/fake-timers": {
- "version": "9.1.2",
- "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz",
- "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==",
- "dev": true,
- "dependencies": {
- "@sinonjs/commons": "^1.7.0"
- }
- },
- "node_modules/@tsconfig/node10": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
- "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==",
- "dev": true
- },
- "node_modules/@tsconfig/node12": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
- "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
- "dev": true
- },
- "node_modules/@tsconfig/node14": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
- "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
- "dev": true
- },
- "node_modules/@tsconfig/node16": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
- "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
- "dev": true
- },
- "node_modules/@types/babel__core": {
- "version": "7.1.20",
- "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.20.tgz",
- "integrity": "sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ==",
- "dev": true,
- "dependencies": {
- "@babel/parser": "^7.1.0",
- "@babel/types": "^7.0.0",
- "@types/babel__generator": "*",
- "@types/babel__template": "*",
- "@types/babel__traverse": "*"
- }
- },
- "node_modules/@types/babel__generator": {
- "version": "7.6.4",
- "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz",
- "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.0.0"
- }
- },
- "node_modules/@types/babel__template": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz",
- "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==",
- "dev": true,
- "dependencies": {
- "@babel/parser": "^7.1.0",
- "@babel/types": "^7.0.0"
- }
- },
- "node_modules/@types/babel__traverse": {
- "version": "7.18.3",
- "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz",
- "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.3.0"
- }
- },
- "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": "26.0.24",
- "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.24.tgz",
- "integrity": "sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w==",
- "dev": true,
- "dependencies": {
- "jest-diff": "^26.0.0",
- "pretty-format": "^26.0.0"
- }
- },
- "node_modules/@types/json-schema": {
- "version": "7.0.11",
- "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
- "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
- "dev": true
- },
- "node_modules/@types/json5": {
- "version": "0.0.29",
- "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
- "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
- "dev": true
- },
- "node_modules/@types/node": {
- "version": "10.17.27",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.27.tgz",
- "integrity": "sha512-J0oqm9ZfAXaPdwNXMMgAhylw5fhmXkToJd06vuDUSAgEDZ/n/69/69UmyBZbc+zT34UnShuDSBqvim3SPnozJg==",
- "dev": true
- },
- "node_modules/@types/prettier": {
- "version": "2.7.2",
- "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz",
- "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==",
- "dev": true
- },
- "node_modules/@types/semver": {
- "version": "7.3.13",
- "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
- "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==",
- "dev": true
- },
- "node_modules/@types/stack-utils": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz",
- "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==",
- "dev": true
- },
- "node_modules/@types/yargs": {
- "version": "17.0.19",
- "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.19.tgz",
- "integrity": "sha512-cAx3qamwaYX9R0fzOIZAlFpo4A+1uBVCxqpKz9D26uTF4srRXaGTTsikQmaotCtNdbhzyUH7ft6p9ktz9s6UNQ==",
- "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/@typescript-eslint/eslint-plugin": {
- "version": "5.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.56.0.tgz",
- "integrity": "sha512-ZNW37Ccl3oMZkzxrYDUX4o7cnuPgU+YrcaYXzsRtLB16I1FR5SHMqga3zGsaSliZADCWo2v8qHWqAYIj8nWCCg==",
- "dev": true,
- "dependencies": {
- "@eslint-community/regexpp": "^4.4.0",
- "@typescript-eslint/scope-manager": "5.56.0",
- "@typescript-eslint/type-utils": "5.56.0",
- "@typescript-eslint/utils": "5.56.0",
- "debug": "^4.3.4",
- "grapheme-splitter": "^1.0.4",
- "ignore": "^5.2.0",
- "natural-compare-lite": "^1.4.0",
- "semver": "^7.3.7",
- "tsutils": "^3.21.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "@typescript-eslint/parser": "^5.0.0",
- "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/@typescript-eslint/eslint-plugin/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/@typescript-eslint/eslint-plugin/node_modules/semver": {
- "version": "7.3.8",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
- "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
- "dev": true,
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@typescript-eslint/eslint-plugin/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/@typescript-eslint/parser": {
- "version": "5.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.56.0.tgz",
- "integrity": "sha512-sn1OZmBxUsgxMmR8a8U5QM/Wl+tyqlH//jTqCg8daTAmhAk26L2PFhcqPLlYBhYUJMZJK276qLXlHN3a83o2cg==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "@typescript-eslint/scope-manager": "5.56.0",
- "@typescript-eslint/types": "5.56.0",
- "@typescript-eslint/typescript-estree": "5.56.0",
- "debug": "^4.3.4"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/@typescript-eslint/scope-manager": {
- "version": "5.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.56.0.tgz",
- "integrity": "sha512-jGYKyt+iBakD0SA5Ww8vFqGpoV2asSjwt60Gl6YcO8ksQ8s2HlUEyHBMSa38bdLopYqGf7EYQMUIGdT/Luw+sw==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/types": "5.56.0",
- "@typescript-eslint/visitor-keys": "5.56.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@typescript-eslint/type-utils": {
- "version": "5.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.56.0.tgz",
- "integrity": "sha512-8WxgOgJjWRy6m4xg9KoSHPzBNZeQbGlQOH7l2QEhQID/+YseaFxg5J/DLwWSsi9Axj4e/cCiKx7PVzOq38tY4A==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/typescript-estree": "5.56.0",
- "@typescript-eslint/utils": "5.56.0",
- "debug": "^4.3.4",
- "tsutils": "^3.21.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "*"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/@typescript-eslint/types": {
- "version": "5.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.56.0.tgz",
- "integrity": "sha512-JyAzbTJcIyhuUhogmiu+t79AkdnqgPUEsxMTMc/dCZczGMJQh1MK2wgrju++yMN6AWroVAy2jxyPcPr3SWCq5w==",
- "dev": true,
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@typescript-eslint/typescript-estree": {
- "version": "5.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.56.0.tgz",
- "integrity": "sha512-41CH/GncsLXOJi0jb74SnC7jVPWeVJ0pxQj8bOjH1h2O26jXN3YHKDT1ejkVz5YeTEQPeLCCRY0U2r68tfNOcg==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/types": "5.56.0",
- "@typescript-eslint/visitor-keys": "5.56.0",
- "debug": "^4.3.4",
- "globby": "^11.1.0",
- "is-glob": "^4.0.3",
- "semver": "^7.3.7",
- "tsutils": "^3.21.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/@typescript-eslint/typescript-estree/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/@typescript-eslint/typescript-estree/node_modules/semver": {
- "version": "7.3.8",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
- "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
- "dev": true,
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@typescript-eslint/typescript-estree/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/@typescript-eslint/utils": {
- "version": "5.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.56.0.tgz",
- "integrity": "sha512-XhZDVdLnUJNtbzaJeDSCIYaM+Tgr59gZGbFuELgF7m0IY03PlciidS7UQNKLE0+WpUTn1GlycEr6Ivb/afjbhA==",
- "dev": true,
- "dependencies": {
- "@eslint-community/eslint-utils": "^4.2.0",
- "@types/json-schema": "^7.0.9",
- "@types/semver": "^7.3.12",
- "@typescript-eslint/scope-manager": "5.56.0",
- "@typescript-eslint/types": "5.56.0",
- "@typescript-eslint/typescript-estree": "5.56.0",
- "eslint-scope": "^5.1.1",
- "semver": "^7.3.7"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
- }
- },
- "node_modules/@typescript-eslint/utils/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/@typescript-eslint/utils/node_modules/semver": {
- "version": "7.3.8",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
- "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
- "dev": true,
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@typescript-eslint/utils/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/@typescript-eslint/visitor-keys": {
- "version": "5.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.56.0.tgz",
- "integrity": "sha512-1mFdED7u5bZpX6Xxf5N9U2c18sb+8EvU3tyOIj6LQZ5OOvnmj8BVeNNP603OFPm5KkS1a7IvCIcwrdHXaEMG/Q==",
- "dev": true,
- "dependencies": {
- "@typescript-eslint/types": "5.56.0",
- "eslint-visitor-keys": "^3.3.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/acorn": {
- "version": "8.8.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz",
- "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==",
- "dev": true,
- "bin": {
- "acorn": "bin/acorn"
- },
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/acorn-jsx": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
- "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
- "dev": true,
- "peerDependencies": {
- "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
- }
- },
- "node_modules/acorn-walk": {
- "version": "8.2.0",
- "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
- "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
- "dev": true,
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "dev": true,
- "dependencies": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
- }
- },
- "node_modules/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/arg": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
- "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
- "dev": true
- },
- "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/array-buffer-byte-length": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
- "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "is-array-buffer": "^3.0.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/array-includes": {
- "version": "3.1.6",
- "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz",
- "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
- "es-abstract": "^1.20.4",
- "get-intrinsic": "^1.1.3",
- "is-string": "^1.0.7"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/array-union": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
- "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/array.prototype.flat": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz",
- "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
- "es-abstract": "^1.20.4",
- "es-shim-unscopables": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/array.prototype.flatmap": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz",
- "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
- "es-abstract": "^1.20.4",
- "es-shim-unscopables": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/available-typed-arrays": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
- "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/aws-cdk": {
- "version": "2.68.0",
- "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.68.0.tgz",
- "integrity": "sha512-r+C5M4J3C7RLiixhxsO/W9Kpb5iB0mFshyn5PXT1cGPkDbx23bnWLOab03jG7uHWIWI01DCipHQyTaeXXqvT3A==",
- "dev": true,
- "bin": {
- "cdk": "bin/cdk"
- },
- "engines": {
- "node": ">= 14.15.0"
- },
- "optionalDependencies": {
- "fsevents": "2.3.2"
- }
- },
- "node_modules/aws-cdk-lib": {
- "version": "2.68.0",
- "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.68.0.tgz",
- "integrity": "sha512-roN3xwzv/GleGG3CaJrf+thdzr9WBzJU4LotumEOs+0cGfeXSta8Pm/cGAeY4kplr5r10QWUovH0fv/bi6Vrbw==",
- "bundleDependencies": [
- "@balena/dockerignore",
- "case",
- "fs-extra",
- "ignore",
- "jsonschema",
- "minimatch",
- "punycode",
- "semver",
- "yaml"
- ],
- "dependencies": {
- "@aws-cdk/asset-awscli-v1": "^2.2.97",
- "@aws-cdk/asset-kubectl-v20": "^2.1.1",
- "@aws-cdk/asset-node-proxy-agent-v5": "^2.0.77",
- "@balena/dockerignore": "^1.0.2",
- "case": "1.6.3",
- "fs-extra": "^9.1.0",
- "ignore": "^5.2.4",
- "jsonschema": "^1.4.1",
- "minimatch": "^3.1.2",
- "punycode": "^2.3.0",
- "semver": "^7.3.8",
- "yaml": "1.10.2"
- },
- "engines": {
- "node": ">= 14.15.0"
- },
- "peerDependencies": {
- "constructs": "^10.0.0"
- }
- },
- "node_modules/aws-cdk-lib/node_modules/@balena/dockerignore": {
- "version": "1.0.2",
- "inBundle": true,
- "license": "Apache-2.0"
- },
- "node_modules/aws-cdk-lib/node_modules/at-least-node": {
- "version": "1.0.0",
- "inBundle": true,
- "license": "ISC",
- "engines": {
- "node": ">= 4.0.0"
- }
- },
- "node_modules/aws-cdk-lib/node_modules/balanced-match": {
- "version": "1.0.2",
- "inBundle": true,
- "license": "MIT"
- },
- "node_modules/aws-cdk-lib/node_modules/brace-expansion": {
- "version": "1.1.11",
- "inBundle": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/aws-cdk-lib/node_modules/case": {
- "version": "1.6.3",
- "inBundle": true,
- "license": "(MIT OR GPL-3.0-or-later)",
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/aws-cdk-lib/node_modules/concat-map": {
- "version": "0.0.1",
- "inBundle": true,
- "license": "MIT"
- },
- "node_modules/aws-cdk-lib/node_modules/fs-extra": {
- "version": "9.1.0",
- "inBundle": true,
- "license": "MIT",
- "dependencies": {
- "at-least-node": "^1.0.0",
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/aws-cdk-lib/node_modules/graceful-fs": {
- "version": "4.2.10",
- "inBundle": true,
- "license": "ISC"
- },
- "node_modules/aws-cdk-lib/node_modules/ignore": {
- "version": "5.2.4",
- "inBundle": true,
- "license": "MIT",
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/aws-cdk-lib/node_modules/jsonfile": {
- "version": "6.1.0",
- "inBundle": true,
- "license": "MIT",
- "dependencies": {
- "universalify": "^2.0.0"
- },
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/aws-cdk-lib/node_modules/jsonschema": {
- "version": "1.4.1",
- "inBundle": true,
- "license": "MIT",
- "engines": {
- "node": "*"
- }
- },
- "node_modules/aws-cdk-lib/node_modules/lru-cache": {
- "version": "6.0.0",
- "inBundle": true,
- "license": "ISC",
- "dependencies": {
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/aws-cdk-lib/node_modules/minimatch": {
- "version": "3.1.2",
- "inBundle": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/aws-cdk-lib/node_modules/punycode": {
- "version": "2.3.0",
- "inBundle": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/aws-cdk-lib/node_modules/semver": {
- "version": "7.3.8",
- "inBundle": true,
- "license": "ISC",
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/aws-cdk-lib/node_modules/universalify": {
- "version": "2.0.0",
- "inBundle": true,
- "license": "MIT",
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/aws-cdk-lib/node_modules/yallist": {
- "version": "4.0.0",
- "inBundle": true,
- "license": "ISC"
- },
- "node_modules/aws-cdk-lib/node_modules/yaml": {
- "version": "1.10.2",
- "inBundle": true,
- "license": "ISC",
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/babel-jest": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.3.1.tgz",
- "integrity": "sha512-aard+xnMoxgjwV70t0L6wkW/3HQQtV+O0PEimxKgzNqCJnbYmroPojdP2tqKSOAt8QAKV/uSZU8851M7B5+fcA==",
- "dev": true,
- "dependencies": {
- "@jest/transform": "^29.3.1",
- "@types/babel__core": "^7.1.14",
- "babel-plugin-istanbul": "^6.1.1",
- "babel-preset-jest": "^29.2.0",
- "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-jest-hoist": {
- "version": "29.2.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.2.0.tgz",
- "integrity": "sha512-TnspP2WNiR3GLfCsUNHqeXw0RoQ2f9U5hQ5L3XFpwuO8htQmSrhh8qsB6vi5Yi8+kuynN1yjDjQsPfkebmB6ZA==",
- "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.2.0",
- "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.2.0.tgz",
- "integrity": "sha512-z9JmMJppMxNv8N7fNRHvhMg9cvIkMxQBXgFkane3yKVEvEOP+kB50lk8DFRvF9PGqbyXxlmebKWhuDORO8RgdA==",
- "dev": true,
- "dependencies": {
- "babel-plugin-jest-hoist": "^29.2.0",
- "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/bowser": {
- "version": "2.11.0",
- "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz",
- "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA=="
- },
- "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.4",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
- "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- }
- ],
- "dependencies": {
- "caniuse-lite": "^1.0.30001400",
- "electron-to-chromium": "^1.4.251",
- "node-releases": "^2.0.6",
- "update-browserslist-db": "^1.0.9"
- },
- "bin": {
- "browserslist": "cli.js"
- },
- "engines": {
- "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
- }
- },
- "node_modules/bs-logger": {
- "version": "0.2.6",
- "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz",
- "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==",
- "dev": true,
- "dependencies": {
- "fast-json-stable-stringify": "2.x"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "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=="
- },
- "node_modules/call-bind": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
- "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
- "dev": true,
- "dependencies": {
- "function-bind": "^1.1.1",
- "get-intrinsic": "^1.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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.30001442",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001442.tgz",
- "integrity": "sha512-239m03Pqy0hwxYPYR5JwOIxRJfLTWtle9FV8zosfV5pHg+/51uD4nxcUlM8+mWWGfwKtt8lJNHnD3cWw9VZ6ow==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
- }
- ]
- },
- "node_modules/cdk-nag": {
- "version": "2.22.23",
- "resolved": "https://registry.npmjs.org/cdk-nag/-/cdk-nag-2.22.23.tgz",
- "integrity": "sha512-bEV7AMqnFBMm/VBdAGgsGd3cKuNNhkriygsb8N7ewO2cY4moQ4RvcAGPxbssm4gfVfanTG8+5XLazYnDsv443Q==",
- "peerDependencies": {
- "aws-cdk-lib": "^2.45.0",
- "constructs": "^10.0.5"
- }
- },
- "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.7.1",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.1.tgz",
- "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/sibiraj-s"
- }
- ],
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cjs-module-lexer": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz",
- "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==",
- "dev": true
- },
- "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.1",
- "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz",
- "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==",
- "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/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/constructs": {
- "version": "10.1.216",
- "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.1.216.tgz",
- "integrity": "sha512-Nx/Pzuyy46Bc5LFu3XPSmTKNcjN4ChQ/R3syOb7bJLfQ5VhJn+o0aCKBVwnbuF1av0YCG6IaDz8fdtWhjefJjA==",
- "engines": {
- "node": ">= 14.17.0"
- }
- },
- "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-require": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
- "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
- "dev": true
- },
- "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/dedent": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
- "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==",
- "dev": true
- },
- "node_modules/deep-is": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
- "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
- "dev": true
- },
- "node_modules/deepmerge": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
- "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/define-properties": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz",
- "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==",
- "dev": true,
- "dependencies": {
- "has-property-descriptors": "^1.0.0",
- "object-keys": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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": "26.6.2",
- "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz",
- "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==",
- "dev": true,
- "engines": {
- "node": ">= 10.14.2"
- }
- },
- "node_modules/dir-glob": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
- "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
- "dev": true,
- "dependencies": {
- "path-type": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/doctrine": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
- "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
- "dev": true,
- "dependencies": {
- "esutils": "^2.0.2"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/electron-to-chromium": {
- "version": "1.4.284",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz",
- "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==",
- "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/es-abstract": {
- "version": "1.21.2",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz",
- "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==",
- "dev": true,
- "dependencies": {
- "array-buffer-byte-length": "^1.0.0",
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.2",
- "es-set-tostringtag": "^2.0.1",
- "es-to-primitive": "^1.2.1",
- "function.prototype.name": "^1.1.5",
- "get-intrinsic": "^1.2.0",
- "get-symbol-description": "^1.0.0",
- "globalthis": "^1.0.3",
- "gopd": "^1.0.1",
- "has": "^1.0.3",
- "has-property-descriptors": "^1.0.0",
- "has-proto": "^1.0.1",
- "has-symbols": "^1.0.3",
- "internal-slot": "^1.0.5",
- "is-array-buffer": "^3.0.2",
- "is-callable": "^1.2.7",
- "is-negative-zero": "^2.0.2",
- "is-regex": "^1.1.4",
- "is-shared-array-buffer": "^1.0.2",
- "is-string": "^1.0.7",
- "is-typed-array": "^1.1.10",
- "is-weakref": "^1.0.2",
- "object-inspect": "^1.12.3",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.4",
- "regexp.prototype.flags": "^1.4.3",
- "safe-regex-test": "^1.0.0",
- "string.prototype.trim": "^1.2.7",
- "string.prototype.trimend": "^1.0.6",
- "string.prototype.trimstart": "^1.0.6",
- "typed-array-length": "^1.0.4",
- "unbox-primitive": "^1.0.2",
- "which-typed-array": "^1.1.9"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/es-set-tostringtag": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
- "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==",
- "dev": true,
- "dependencies": {
- "get-intrinsic": "^1.1.3",
- "has": "^1.0.3",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-shim-unscopables": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz",
- "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==",
- "dev": true,
- "dependencies": {
- "has": "^1.0.3"
- }
- },
- "node_modules/es-to-primitive": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
- "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
- "dev": true,
- "dependencies": {
- "is-callable": "^1.1.4",
- "is-date-object": "^1.0.1",
- "is-symbol": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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/eslint": {
- "version": "8.36.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz",
- "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==",
- "dev": true,
- "dependencies": {
- "@eslint-community/eslint-utils": "^4.2.0",
- "@eslint-community/regexpp": "^4.4.0",
- "@eslint/eslintrc": "^2.0.1",
- "@eslint/js": "8.36.0",
- "@humanwhocodes/config-array": "^0.11.8",
- "@humanwhocodes/module-importer": "^1.0.1",
- "@nodelib/fs.walk": "^1.2.8",
- "ajv": "^6.10.0",
- "chalk": "^4.0.0",
- "cross-spawn": "^7.0.2",
- "debug": "^4.3.2",
- "doctrine": "^3.0.0",
- "escape-string-regexp": "^4.0.0",
- "eslint-scope": "^7.1.1",
- "eslint-visitor-keys": "^3.3.0",
- "espree": "^9.5.0",
- "esquery": "^1.4.2",
- "esutils": "^2.0.2",
- "fast-deep-equal": "^3.1.3",
- "file-entry-cache": "^6.0.1",
- "find-up": "^5.0.0",
- "glob-parent": "^6.0.2",
- "globals": "^13.19.0",
- "grapheme-splitter": "^1.0.4",
- "ignore": "^5.2.0",
- "import-fresh": "^3.0.0",
- "imurmurhash": "^0.1.4",
- "is-glob": "^4.0.0",
- "is-path-inside": "^3.0.3",
- "js-sdsl": "^4.1.4",
- "js-yaml": "^4.1.0",
- "json-stable-stringify-without-jsonify": "^1.0.1",
- "levn": "^0.4.1",
- "lodash.merge": "^4.6.2",
- "minimatch": "^3.1.2",
- "natural-compare": "^1.4.0",
- "optionator": "^0.9.1",
- "strip-ansi": "^6.0.1",
- "strip-json-comments": "^3.1.0",
- "text-table": "^0.2.0"
- },
- "bin": {
- "eslint": "bin/eslint.js"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/eslint-config-prettier": {
- "version": "8.8.0",
- "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz",
- "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==",
- "dev": true,
- "bin": {
- "eslint-config-prettier": "bin/cli.js"
- },
- "peerDependencies": {
- "eslint": ">=7.0.0"
- }
- },
- "node_modules/eslint-import-resolver-node": {
- "version": "0.3.7",
- "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz",
- "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==",
- "dev": true,
- "dependencies": {
- "debug": "^3.2.7",
- "is-core-module": "^2.11.0",
- "resolve": "^1.22.1"
- }
- },
- "node_modules/eslint-import-resolver-node/node_modules/debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
- "dev": true,
- "dependencies": {
- "ms": "^2.1.1"
- }
- },
- "node_modules/eslint-module-utils": {
- "version": "2.7.4",
- "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz",
- "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==",
- "dev": true,
- "dependencies": {
- "debug": "^3.2.7"
- },
- "engines": {
- "node": ">=4"
- },
- "peerDependenciesMeta": {
- "eslint": {
- "optional": true
- }
- }
- },
- "node_modules/eslint-module-utils/node_modules/debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
- "dev": true,
- "dependencies": {
- "ms": "^2.1.1"
- }
- },
- "node_modules/eslint-plugin-header": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-header/-/eslint-plugin-header-3.1.1.tgz",
- "integrity": "sha512-9vlKxuJ4qf793CmeeSrZUvVClw6amtpghq3CuWcB5cUNnWHQhgcqy5eF8oVKFk1G3Y/CbchGfEaw3wiIJaNmVg==",
- "dev": true,
- "peerDependencies": {
- "eslint": ">=7.7.0"
- }
- },
- "node_modules/eslint-plugin-import": {
- "version": "2.27.5",
- "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz",
- "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==",
- "dev": true,
- "dependencies": {
- "array-includes": "^3.1.6",
- "array.prototype.flat": "^1.3.1",
- "array.prototype.flatmap": "^1.3.1",
- "debug": "^3.2.7",
- "doctrine": "^2.1.0",
- "eslint-import-resolver-node": "^0.3.7",
- "eslint-module-utils": "^2.7.4",
- "has": "^1.0.3",
- "is-core-module": "^2.11.0",
- "is-glob": "^4.0.3",
- "minimatch": "^3.1.2",
- "object.values": "^1.1.6",
- "resolve": "^1.22.1",
- "semver": "^6.3.0",
- "tsconfig-paths": "^3.14.1"
- },
- "engines": {
- "node": ">=4"
- },
- "peerDependencies": {
- "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
- }
- },
- "node_modules/eslint-plugin-import/node_modules/debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
- "dev": true,
- "dependencies": {
- "ms": "^2.1.1"
- }
- },
- "node_modules/eslint-plugin-import/node_modules/doctrine": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
- "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
- "dev": true,
- "dependencies": {
- "esutils": "^2.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/eslint-plugin-prettier": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz",
- "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==",
- "dev": true,
- "dependencies": {
- "prettier-linter-helpers": "^1.0.0"
- },
- "engines": {
- "node": ">=12.0.0"
- },
- "peerDependencies": {
- "eslint": ">=7.28.0",
- "prettier": ">=2.0.0"
- },
- "peerDependenciesMeta": {
- "eslint-config-prettier": {
- "optional": true
- }
- }
- },
- "node_modules/eslint-scope": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
- "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
- "dev": true,
- "dependencies": {
- "esrecurse": "^4.3.0",
- "estraverse": "^4.1.1"
- },
- "engines": {
- "node": ">=8.0.0"
- }
- },
- "node_modules/eslint-visitor-keys": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
- "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
- "dev": true,
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- }
- },
- "node_modules/eslint/node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true
- },
- "node_modules/eslint/node_modules/escape-string-regexp": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
- "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/eslint/node_modules/eslint-scope": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
- "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
- "dev": true,
- "dependencies": {
- "esrecurse": "^4.3.0",
- "estraverse": "^5.2.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- }
- },
- "node_modules/eslint/node_modules/estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
- "dev": true,
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/eslint/node_modules/find-up": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
- "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
- "dev": true,
- "dependencies": {
- "locate-path": "^6.0.0",
- "path-exists": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/eslint/node_modules/globals": {
- "version": "13.20.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
- "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
- "dev": true,
- "dependencies": {
- "type-fest": "^0.20.2"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/eslint/node_modules/js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
- "dev": true,
- "dependencies": {
- "argparse": "^2.0.1"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
- "node_modules/eslint/node_modules/locate-path": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
- "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
- "dev": true,
- "dependencies": {
- "p-locate": "^5.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/eslint/node_modules/p-locate": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
- "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
- "dev": true,
- "dependencies": {
- "p-limit": "^3.0.2"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/eslint/node_modules/type-fest": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
- "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/espree": {
- "version": "9.5.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz",
- "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==",
- "dev": true,
- "dependencies": {
- "acorn": "^8.8.0",
- "acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^3.3.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "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/esquery": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
- "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
- "dev": true,
- "dependencies": {
- "estraverse": "^5.1.0"
- },
- "engines": {
- "node": ">=0.10"
- }
- },
- "node_modules/esquery/node_modules/estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
- "dev": true,
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/esrecurse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
- "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
- "dev": true,
- "dependencies": {
- "estraverse": "^5.2.0"
- },
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/esrecurse/node_modules/estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
- "dev": true,
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/estraverse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
- "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
- "dev": true,
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/esutils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
- "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "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.3.1",
- "resolved": "https://registry.npmjs.org/expect/-/expect-29.3.1.tgz",
- "integrity": "sha512-gGb1yTgU30Q0O/tQq+z30KBWv24ApkMgFUpvKBkyLUBL68Wv8dHdJxTBZFl/iT8K/bqDHvUYRH6IIN3rToopPA==",
- "dev": true,
- "dependencies": {
- "@jest/expect-utils": "^29.3.1",
- "jest-get-type": "^29.2.0",
- "jest-matcher-utils": "^29.3.1",
- "jest-message-util": "^29.3.1",
- "jest-util": "^29.3.1"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "dev": true
- },
- "node_modules/fast-diff": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
- "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
- "dev": true
- },
- "node_modules/fast-glob": {
- "version": "3.2.12",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
- "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.4"
- },
- "engines": {
- "node": ">=8.6.0"
- }
- },
- "node_modules/fast-glob/node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "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/fast-levenshtein": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
- "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
- "dev": true
- },
- "node_modules/fast-xml-parser": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.1.2.tgz",
- "integrity": "sha512-CDYeykkle1LiA/uqQyNwYpFbyF6Axec6YapmpUP+/RHWIoR1zKjocdvNaTsxCxZzQ6v9MLXaSYm9Qq0thv0DHg==",
- "dependencies": {
- "strnum": "^1.0.5"
- },
- "bin": {
- "fxparser": "src/cli/cli.js"
- },
- "funding": {
- "type": "paypal",
- "url": "https://paypal.me/naturalintelligence"
- }
- },
- "node_modules/fastq": {
- "version": "1.15.0",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
- "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
- "dev": true,
- "dependencies": {
- "reusify": "^1.0.4"
- }
- },
- "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/file-entry-cache": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
- "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
- "dev": true,
- "dependencies": {
- "flat-cache": "^3.0.4"
- },
- "engines": {
- "node": "^10.12.0 || >=12.0.0"
- }
- },
- "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/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/flat-cache": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
- "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
- "dev": true,
- "dependencies": {
- "flatted": "^3.1.0",
- "rimraf": "^3.0.2"
- },
- "engines": {
- "node": "^10.12.0 || >=12.0.0"
- }
- },
- "node_modules/flatted": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
- "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
- "dev": true
- },
- "node_modules/for-each": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
- "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
- "dev": true,
- "dependencies": {
- "is-callable": "^1.1.3"
- }
- },
- "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.2",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
- "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
- "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/function.prototype.name": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
- "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.3",
- "es-abstract": "^1.19.0",
- "functions-have-names": "^1.2.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/functions-have-names": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
- "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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-intrinsic": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
- "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==",
- "dev": true,
- "dependencies": {
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.3"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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/get-symbol-description": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
- "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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/glob-parent": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
- "dependencies": {
- "is-glob": "^4.0.3"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "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/globalthis": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
- "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
- "dev": true,
- "dependencies": {
- "define-properties": "^1.1.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/globby": {
- "version": "11.1.0",
- "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
- "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
- "dev": true,
- "dependencies": {
- "array-union": "^2.1.0",
- "dir-glob": "^3.0.1",
- "fast-glob": "^3.2.9",
- "ignore": "^5.2.0",
- "merge2": "^1.4.1",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/gopd": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
- "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
- "dev": true,
- "dependencies": {
- "get-intrinsic": "^1.1.3"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/graceful-fs": {
- "version": "4.2.10",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
- "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
- "dev": true
- },
- "node_modules/grapheme-splitter": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
- "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
- "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-bigints": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
- "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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/has-property-descriptors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
- "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
- "dev": true,
- "dependencies": {
- "get-intrinsic": "^1.1.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
- "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-symbols": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
- "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-tostringtag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
- "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
- "dev": true,
- "dependencies": {
- "has-symbols": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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/ignore": {
- "version": "5.2.4",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
- "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
- "dev": true,
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/import-fresh": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
- "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
- "dev": true,
- "dependencies": {
- "parent-module": "^1.0.0",
- "resolve-from": "^4.0.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/import-fresh/node_modules/resolve-from": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
- "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "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/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/internal-slot": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz",
- "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==",
- "dev": true,
- "dependencies": {
- "get-intrinsic": "^1.2.0",
- "has": "^1.0.3",
- "side-channel": "^1.0.4"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/is-array-buffer": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
- "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.2.0",
- "is-typed-array": "^1.1.10"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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-bigint": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
- "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
- "dev": true,
- "dependencies": {
- "has-bigints": "^1.0.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-boolean-object": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
- "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-callable": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
- "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-core-module": {
- "version": "2.11.0",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
- "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
- "dev": true,
- "dependencies": {
- "has": "^1.0.3"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-date-object": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
- "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
- "dev": true,
- "dependencies": {
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "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-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
- "dependencies": {
- "is-extglob": "^2.1.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-negative-zero": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
- "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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-number-object": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
- "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
- "dev": true,
- "dependencies": {
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-path-inside": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
- "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-regex": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
- "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-shared-array-buffer": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
- "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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/is-string": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
- "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
- "dev": true,
- "dependencies": {
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-symbol": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
- "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
- "dev": true,
- "dependencies": {
- "has-symbols": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-typed-array": {
- "version": "1.1.10",
- "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz",
- "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==",
- "dev": true,
- "dependencies": {
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.2",
- "for-each": "^0.3.3",
- "gopd": "^1.0.1",
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-weakref": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
- "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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": "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/istanbul-lib-report": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
- "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==",
- "dev": true,
- "dependencies": {
- "istanbul-lib-coverage": "^3.0.0",
- "make-dir": "^3.0.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "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.5",
- "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz",
- "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==",
- "dev": true,
- "dependencies": {
- "html-escaper": "^2.0.0",
- "istanbul-lib-report": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/jest": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest/-/jest-29.3.1.tgz",
- "integrity": "sha512-6iWfL5DTT0Np6UYs/y5Niu7WIfNv/wRTtN5RSXt2DIEft3dx3zPuw/3WJQBCJfmEzvDiEKwoqMbGD9n49+qLSA==",
- "dev": true,
- "dependencies": {
- "@jest/core": "^29.3.1",
- "@jest/types": "^29.3.1",
- "import-local": "^3.0.2",
- "jest-cli": "^29.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-changed-files": {
- "version": "29.2.0",
- "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.2.0.tgz",
- "integrity": "sha512-qPVmLLyBmvF5HJrY7krDisx6Voi8DmlV3GZYX0aFNbaQsZeoz1hfxcCMbqDGuQCxU1dJy9eYc2xscE8QrCCYaA==",
- "dev": true,
- "dependencies": {
- "execa": "^5.0.0",
- "p-limit": "^3.1.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-circus": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.3.1.tgz",
- "integrity": "sha512-wpr26sEvwb3qQQbdlmei+gzp6yoSSoSL6GsLPxnuayZSMrSd5Ka7IjAvatpIernBvT2+Ic6RLTg+jSebScmasg==",
- "dev": true,
- "dependencies": {
- "@jest/environment": "^29.3.1",
- "@jest/expect": "^29.3.1",
- "@jest/test-result": "^29.3.1",
- "@jest/types": "^29.3.1",
- "@types/node": "*",
- "chalk": "^4.0.0",
- "co": "^4.6.0",
- "dedent": "^0.7.0",
- "is-generator-fn": "^2.0.0",
- "jest-each": "^29.3.1",
- "jest-matcher-utils": "^29.3.1",
- "jest-message-util": "^29.3.1",
- "jest-runtime": "^29.3.1",
- "jest-snapshot": "^29.3.1",
- "jest-util": "^29.3.1",
- "p-limit": "^3.1.0",
- "pretty-format": "^29.3.1",
- "slash": "^3.0.0",
- "stack-utils": "^2.0.3"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-circus/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/jest-circus/node_modules/pretty-format": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz",
- "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==",
- "dev": true,
- "dependencies": {
- "@jest/schemas": "^29.0.0",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-circus/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/jest-cli": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.3.1.tgz",
- "integrity": "sha512-TO/ewvwyvPOiBBuWZ0gm04z3WWP8TIK8acgPzE4IxgsLKQgb377NYGrQLc3Wl/7ndWzIH2CDNNsUjGxwLL43VQ==",
- "dev": true,
- "dependencies": {
- "@jest/core": "^29.3.1",
- "@jest/test-result": "^29.3.1",
- "@jest/types": "^29.3.1",
- "chalk": "^4.0.0",
- "exit": "^0.1.2",
- "graceful-fs": "^4.2.9",
- "import-local": "^3.0.2",
- "jest-config": "^29.3.1",
- "jest-util": "^29.3.1",
- "jest-validate": "^29.3.1",
- "prompts": "^2.0.1",
- "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.3.1",
- "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.3.1.tgz",
- "integrity": "sha512-y0tFHdj2WnTEhxmGUK1T7fgLen7YK4RtfvpLFBXfQkh2eMJAQq24Vx9472lvn5wg0MAO6B+iPfJfzdR9hJYalg==",
- "dev": true,
- "dependencies": {
- "@babel/core": "^7.11.6",
- "@jest/test-sequencer": "^29.3.1",
- "@jest/types": "^29.3.1",
- "babel-jest": "^29.3.1",
- "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.3.1",
- "jest-environment-node": "^29.3.1",
- "jest-get-type": "^29.2.0",
- "jest-regex-util": "^29.2.0",
- "jest-resolve": "^29.3.1",
- "jest-runner": "^29.3.1",
- "jest-util": "^29.3.1",
- "jest-validate": "^29.3.1",
- "micromatch": "^4.0.4",
- "parse-json": "^5.2.0",
- "pretty-format": "^29.3.1",
- "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-config/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/jest-config/node_modules/pretty-format": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz",
- "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==",
- "dev": true,
- "dependencies": {
- "@jest/schemas": "^29.0.0",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-config/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/jest-diff": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz",
- "integrity": "sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==",
- "dev": true,
- "dependencies": {
- "chalk": "^4.0.0",
- "diff-sequences": "^26.6.2",
- "jest-get-type": "^26.3.0",
- "pretty-format": "^26.6.2"
- },
- "engines": {
- "node": ">= 10.14.2"
- }
- },
- "node_modules/jest-diff/node_modules/jest-get-type": {
- "version": "26.3.0",
- "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz",
- "integrity": "sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==",
- "dev": true,
- "engines": {
- "node": ">= 10.14.2"
- }
- },
- "node_modules/jest-docblock": {
- "version": "29.2.0",
- "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.2.0.tgz",
- "integrity": "sha512-bkxUsxTgWQGbXV5IENmfiIuqZhJcyvF7tU4zJ/7ioTutdz4ToB5Yx6JOFBpgI+TphRY4lhOyCWGNH/QFQh5T6A==",
- "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.3.1",
- "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.3.1.tgz",
- "integrity": "sha512-qrZH7PmFB9rEzCSl00BWjZYuS1BSOH8lLuC0azQE9lQrAx3PWGKHTDudQiOSwIy5dGAJh7KA0ScYlCP7JxvFYA==",
- "dev": true,
- "dependencies": {
- "@jest/types": "^29.3.1",
- "chalk": "^4.0.0",
- "jest-get-type": "^29.2.0",
- "jest-util": "^29.3.1",
- "pretty-format": "^29.3.1"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-each/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/jest-each/node_modules/pretty-format": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz",
- "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==",
- "dev": true,
- "dependencies": {
- "@jest/schemas": "^29.0.0",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-each/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/jest-environment-node": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.3.1.tgz",
- "integrity": "sha512-xm2THL18Xf5sIHoU7OThBPtuH6Lerd+Y1NLYiZJlkE3hbE+7N7r8uvHIl/FkZ5ymKXJe/11SQuf3fv4v6rUMag==",
- "dev": true,
- "dependencies": {
- "@jest/environment": "^29.3.1",
- "@jest/fake-timers": "^29.3.1",
- "@jest/types": "^29.3.1",
- "@types/node": "*",
- "jest-mock": "^29.3.1",
- "jest-util": "^29.3.1"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-extended": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/jest-extended/-/jest-extended-3.2.4.tgz",
- "integrity": "sha512-lSEYhSmvXZG/7YXI7KO3LpiUiQ90gi5giwCJNDMMsX5a+/NZhdbQF2G4ALOBN+KcXVT3H6FPVPohAuMXooaLTQ==",
- "dev": true,
- "dependencies": {
- "jest-diff": "^29.0.0",
- "jest-get-type": "^29.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- },
- "peerDependencies": {
- "jest": ">=27.2.5"
- },
- "peerDependenciesMeta": {
- "jest": {
- "optional": true
- }
- }
- },
- "node_modules/jest-extended/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/jest-extended/node_modules/diff-sequences": {
- "version": "29.4.3",
- "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz",
- "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==",
- "dev": true,
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-extended/node_modules/jest-diff": {
- "version": "29.5.0",
- "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz",
- "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==",
- "dev": true,
- "dependencies": {
- "chalk": "^4.0.0",
- "diff-sequences": "^29.4.3",
- "jest-get-type": "^29.4.3",
- "pretty-format": "^29.5.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-extended/node_modules/pretty-format": {
- "version": "29.5.0",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz",
- "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==",
- "dev": true,
- "dependencies": {
- "@jest/schemas": "^29.4.3",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-extended/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/jest-get-type": {
- "version": "29.4.3",
- "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz",
- "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==",
- "dev": true,
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-haste-map": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.3.1.tgz",
- "integrity": "sha512-/FFtvoG1xjbbPXQLFef+WSU4yrc0fc0Dds6aRPBojUid7qlPqZvxdUBA03HW0fnVHXVCnCdkuoghYItKNzc/0A==",
- "dev": true,
- "dependencies": {
- "@jest/types": "^29.3.1",
- "@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.2.0",
- "jest-util": "^29.3.1",
- "jest-worker": "^29.3.1",
- "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-junit": {
- "version": "15.0.0",
- "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-15.0.0.tgz",
- "integrity": "sha512-Z5sVX0Ag3HZdMUnD5DFlG+1gciIFSy7yIVPhOdGUi8YJaI9iLvvBb530gtQL2CHmv0JJeiwRZenr0VrSR7frvg==",
- "dev": true,
- "dependencies": {
- "mkdirp": "^1.0.4",
- "strip-ansi": "^6.0.1",
- "uuid": "^8.3.2",
- "xml": "^1.0.1"
- },
- "engines": {
- "node": ">=10.12.0"
- }
- },
- "node_modules/jest-leak-detector": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.3.1.tgz",
- "integrity": "sha512-3DA/VVXj4zFOPagGkuqHnSQf1GZBmmlagpguxEERO6Pla2g84Q1MaVIB3YMxgUaFIaYag8ZnTyQgiZ35YEqAQA==",
- "dev": true,
- "dependencies": {
- "jest-get-type": "^29.2.0",
- "pretty-format": "^29.3.1"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-leak-detector/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/jest-leak-detector/node_modules/pretty-format": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz",
- "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==",
- "dev": true,
- "dependencies": {
- "@jest/schemas": "^29.0.0",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-leak-detector/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/jest-matcher-utils": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.3.1.tgz",
- "integrity": "sha512-fkRMZUAScup3txIKfMe3AIZZmPEjWEdsPJFK3AIy5qRohWqQFg1qrmKfYXR9qEkNc7OdAu2N4KPHibEmy4HPeQ==",
- "dev": true,
- "dependencies": {
- "chalk": "^4.0.0",
- "jest-diff": "^29.3.1",
- "jest-get-type": "^29.2.0",
- "pretty-format": "^29.3.1"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-matcher-utils/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/jest-matcher-utils/node_modules/diff-sequences": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.3.1.tgz",
- "integrity": "sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==",
- "dev": true,
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-matcher-utils/node_modules/jest-diff": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.3.1.tgz",
- "integrity": "sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw==",
- "dev": true,
- "dependencies": {
- "chalk": "^4.0.0",
- "diff-sequences": "^29.3.1",
- "jest-get-type": "^29.2.0",
- "pretty-format": "^29.3.1"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-matcher-utils/node_modules/pretty-format": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz",
- "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==",
- "dev": true,
- "dependencies": {
- "@jest/schemas": "^29.0.0",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-matcher-utils/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/jest-message-util": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.3.1.tgz",
- "integrity": "sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA==",
- "dev": true,
- "dependencies": {
- "@babel/code-frame": "^7.12.13",
- "@jest/types": "^29.3.1",
- "@types/stack-utils": "^2.0.0",
- "chalk": "^4.0.0",
- "graceful-fs": "^4.2.9",
- "micromatch": "^4.0.4",
- "pretty-format": "^29.3.1",
- "slash": "^3.0.0",
- "stack-utils": "^2.0.3"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-message-util/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/jest-message-util/node_modules/pretty-format": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz",
- "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==",
- "dev": true,
- "dependencies": {
- "@jest/schemas": "^29.0.0",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-message-util/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/jest-mock": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.3.1.tgz",
- "integrity": "sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA==",
- "dev": true,
- "dependencies": {
- "@jest/types": "^29.3.1",
- "@types/node": "*",
- "jest-util": "^29.3.1"
- },
- "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.2.0",
- "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.2.0.tgz",
- "integrity": "sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA==",
- "dev": true,
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-resolve": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.3.1.tgz",
- "integrity": "sha512-amXJgH/Ng712w3Uz5gqzFBBjxV8WFLSmNjoreBGMqxgCz5cH7swmBZzgBaCIOsvb0NbpJ0vgaSFdJqMdT+rADw==",
- "dev": true,
- "dependencies": {
- "chalk": "^4.0.0",
- "graceful-fs": "^4.2.9",
- "jest-haste-map": "^29.3.1",
- "jest-pnp-resolver": "^1.2.2",
- "jest-util": "^29.3.1",
- "jest-validate": "^29.3.1",
- "resolve": "^1.20.0",
- "resolve.exports": "^1.1.0",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-resolve-dependencies": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.3.1.tgz",
- "integrity": "sha512-Vk0cYq0byRw2WluNmNWGqPeRnZ3p3hHmjJMp2dyyZeYIfiBskwq4rpiuGFR6QGAdbj58WC7HN4hQHjf2mpvrLA==",
- "dev": true,
- "dependencies": {
- "jest-regex-util": "^29.2.0",
- "jest-snapshot": "^29.3.1"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-runner": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.3.1.tgz",
- "integrity": "sha512-oFvcwRNrKMtE6u9+AQPMATxFcTySyKfLhvso7Sdk/rNpbhg4g2GAGCopiInk1OP4q6gz3n6MajW4+fnHWlU3bA==",
- "dev": true,
- "dependencies": {
- "@jest/console": "^29.3.1",
- "@jest/environment": "^29.3.1",
- "@jest/test-result": "^29.3.1",
- "@jest/transform": "^29.3.1",
- "@jest/types": "^29.3.1",
- "@types/node": "*",
- "chalk": "^4.0.0",
- "emittery": "^0.13.1",
- "graceful-fs": "^4.2.9",
- "jest-docblock": "^29.2.0",
- "jest-environment-node": "^29.3.1",
- "jest-haste-map": "^29.3.1",
- "jest-leak-detector": "^29.3.1",
- "jest-message-util": "^29.3.1",
- "jest-resolve": "^29.3.1",
- "jest-runtime": "^29.3.1",
- "jest-util": "^29.3.1",
- "jest-watcher": "^29.3.1",
- "jest-worker": "^29.3.1",
- "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-runner/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/jest-runtime": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.3.1.tgz",
- "integrity": "sha512-jLzkIxIqXwBEOZx7wx9OO9sxoZmgT2NhmQKzHQm1xwR1kNW/dn0OjxR424VwHHf1SPN6Qwlb5pp1oGCeFTQ62A==",
- "dev": true,
- "dependencies": {
- "@jest/environment": "^29.3.1",
- "@jest/fake-timers": "^29.3.1",
- "@jest/globals": "^29.3.1",
- "@jest/source-map": "^29.2.0",
- "@jest/test-result": "^29.3.1",
- "@jest/transform": "^29.3.1",
- "@jest/types": "^29.3.1",
- "@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.3.1",
- "jest-message-util": "^29.3.1",
- "jest-mock": "^29.3.1",
- "jest-regex-util": "^29.2.0",
- "jest-resolve": "^29.3.1",
- "jest-snapshot": "^29.3.1",
- "jest-util": "^29.3.1",
- "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.3.1",
- "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.3.1.tgz",
- "integrity": "sha512-+3JOc+s28upYLI2OJM4PWRGK9AgpsMs/ekNryUV0yMBClT9B1DF2u2qay8YxcQd338PPYSFNb0lsar1B49sLDA==",
- "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/traverse": "^7.7.2",
- "@babel/types": "^7.3.3",
- "@jest/expect-utils": "^29.3.1",
- "@jest/transform": "^29.3.1",
- "@jest/types": "^29.3.1",
- "@types/babel__traverse": "^7.0.6",
- "@types/prettier": "^2.1.5",
- "babel-preset-current-node-syntax": "^1.0.0",
- "chalk": "^4.0.0",
- "expect": "^29.3.1",
- "graceful-fs": "^4.2.9",
- "jest-diff": "^29.3.1",
- "jest-get-type": "^29.2.0",
- "jest-haste-map": "^29.3.1",
- "jest-matcher-utils": "^29.3.1",
- "jest-message-util": "^29.3.1",
- "jest-util": "^29.3.1",
- "natural-compare": "^1.4.0",
- "pretty-format": "^29.3.1",
- "semver": "^7.3.5"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-snapshot/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/jest-snapshot/node_modules/diff-sequences": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.3.1.tgz",
- "integrity": "sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==",
- "dev": true,
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-snapshot/node_modules/jest-diff": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.3.1.tgz",
- "integrity": "sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw==",
- "dev": true,
- "dependencies": {
- "chalk": "^4.0.0",
- "diff-sequences": "^29.3.1",
- "jest-get-type": "^29.2.0",
- "pretty-format": "^29.3.1"
- },
- "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/pretty-format": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz",
- "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==",
- "dev": true,
- "dependencies": {
- "@jest/schemas": "^29.0.0",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-snapshot/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/jest-snapshot/node_modules/semver": {
- "version": "7.3.8",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
- "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
- "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.3.1",
- "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.3.1.tgz",
- "integrity": "sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ==",
- "dev": true,
- "dependencies": {
- "@jest/types": "^29.3.1",
- "@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.3.1",
- "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.3.1.tgz",
- "integrity": "sha512-N9Lr3oYR2Mpzuelp1F8negJR3YE+L1ebk1rYA5qYo9TTY3f9OWdptLoNSPP9itOCBIRBqjt/S5XHlzYglLN67g==",
- "dev": true,
- "dependencies": {
- "@jest/types": "^29.3.1",
- "camelcase": "^6.2.0",
- "chalk": "^4.0.0",
- "jest-get-type": "^29.2.0",
- "leven": "^3.1.0",
- "pretty-format": "^29.3.1"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-validate/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/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-validate/node_modules/pretty-format": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz",
- "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==",
- "dev": true,
- "dependencies": {
- "@jest/schemas": "^29.0.0",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-validate/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/jest-watcher": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.3.1.tgz",
- "integrity": "sha512-RspXG2BQFDsZSRKGCT/NiNa8RkQ1iKAjrO0//soTMWx/QUt+OcxMqMSBxz23PYGqUuWm2+m2mNNsmj0eIoOaFg==",
- "dev": true,
- "dependencies": {
- "@jest/test-result": "^29.3.1",
- "@jest/types": "^29.3.1",
- "@types/node": "*",
- "ansi-escapes": "^4.2.1",
- "chalk": "^4.0.0",
- "emittery": "^0.13.1",
- "jest-util": "^29.3.1",
- "string-length": "^4.0.1"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-worker": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.3.1.tgz",
- "integrity": "sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw==",
- "dev": true,
- "dependencies": {
- "@types/node": "*",
- "jest-util": "^29.3.1",
- "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-sdsl": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz",
- "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==",
- "dev": true,
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/js-sdsl"
- }
- },
- "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/json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true
- },
- "node_modules/json-stable-stringify-without-jsonify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
- "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
- "dev": true
- },
- "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/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/levn": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
- "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
- "dev": true,
- "dependencies": {
- "prelude-ls": "^1.2.1",
- "type-check": "~0.4.0"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "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.memoize": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
- "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==",
- "dev": true
- },
- "node_modules/lodash.merge": {
- "version": "4.6.2",
- "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
- "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
- "dev": true
- },
- "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": "3.1.0",
- "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
- "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
- "dev": true,
- "dependencies": {
- "semver": "^6.0.0"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/make-error": {
- "version": "1.3.6",
- "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
- "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
- "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/merge2": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
- "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
- "dev": true,
- "engines": {
- "node": ">= 8"
- }
- },
- "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/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/minimist": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
- "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/mkdirp": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
- "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
- "dev": true,
- "bin": {
- "mkdirp": "bin/cmd.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/mnemonist": {
- "version": "0.38.3",
- "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.3.tgz",
- "integrity": "sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==",
- "dependencies": {
- "obliterator": "^1.6.1"
- }
- },
- "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/natural-compare-lite": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
- "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
- "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.8",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz",
- "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==",
- "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/object-inspect": {
- "version": "1.12.3",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
- "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/object.assign": {
- "version": "4.1.4",
- "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
- "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
- "has-symbols": "^1.0.3",
- "object-keys": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/object.values": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz",
- "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
- "es-abstract": "^1.20.4"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/obliterator": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-1.6.1.tgz",
- "integrity": "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig=="
- },
- "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/optionator": {
- "version": "0.9.1",
- "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
- "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
- "dev": true,
- "dependencies": {
- "deep-is": "^0.1.3",
- "fast-levenshtein": "^2.0.6",
- "levn": "^0.4.1",
- "prelude-ls": "^1.2.1",
- "type-check": "^0.4.0",
- "word-wrap": "^1.2.3"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "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/parent-module": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
- "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
- "dev": true,
- "dependencies": {
- "callsites": "^3.0.0"
- },
- "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/path-type": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
- "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "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.5",
- "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz",
- "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==",
- "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/prelude-ls": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
- "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
- "dev": true,
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/prettier": {
- "version": "2.8.7",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.7.tgz",
- "integrity": "sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==",
- "dev": true,
- "peer": true,
- "bin": {
- "prettier": "bin-prettier.js"
- },
- "engines": {
- "node": ">=10.13.0"
- },
- "funding": {
- "url": "https://github.com/prettier/prettier?sponsor=1"
- }
- },
- "node_modules/prettier-linter-helpers": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
- "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
- "dev": true,
- "dependencies": {
- "fast-diff": "^1.1.2"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/pretty-format": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz",
- "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==",
- "dev": true,
- "dependencies": {
- "@jest/types": "^26.6.2",
- "ansi-regex": "^5.0.0",
- "ansi-styles": "^4.0.0",
- "react-is": "^17.0.1"
- },
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/pretty-format/node_modules/@jest/types": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz",
- "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==",
- "dev": true,
- "dependencies": {
- "@types/istanbul-lib-coverage": "^2.0.0",
- "@types/istanbul-reports": "^3.0.0",
- "@types/node": "*",
- "@types/yargs": "^15.0.0",
- "chalk": "^4.0.0"
- },
- "engines": {
- "node": ">= 10.14.2"
- }
- },
- "node_modules/pretty-format/node_modules/@types/yargs": {
- "version": "15.0.15",
- "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.15.tgz",
- "integrity": "sha512-IziEYMU9XoVj8hWg7k+UJrXALkGFjWJhn5QFEv9q4p+v40oZhSuC135M38st8XPjICL7Ey4TV64ferBGUoJhBg==",
- "dev": true,
- "dependencies": {
- "@types/yargs-parser": "*"
- }
- },
- "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/punycode": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
- "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/queue-microtask": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
- "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ]
- },
- "node_modules/react-is": {
- "version": "17.0.2",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
- "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
- "dev": true
- },
- "node_modules/regexp.prototype.flags": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
- "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.3",
- "functions-have-names": "^1.2.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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.1",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
- "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
- "dev": true,
- "dependencies": {
- "is-core-module": "^2.9.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": "1.1.0",
- "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz",
- "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==",
- "dev": true,
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/reusify": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
- "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
- "dev": true,
- "engines": {
- "iojs": ">=1.0.0",
- "node": ">=0.10.0"
- }
- },
- "node_modules/rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "dev": true,
- "dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/run-parallel": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
- "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "dependencies": {
- "queue-microtask": "^1.2.2"
- }
- },
- "node_modules/safe-regex-test": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz",
- "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.1.3",
- "is-regex": "^1.1.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
- "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/side-channel": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
- "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.0",
- "get-intrinsic": "^1.0.2",
- "object-inspect": "^1.9.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/source-map-support": {
- "version": "0.5.21",
- "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
- "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
- "dependencies": {
- "buffer-from": "^1.0.0",
- "source-map": "^0.6.0"
- }
- },
- "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/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/string.prototype.trim": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz",
- "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
- "es-abstract": "^1.20.4"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/string.prototype.trimend": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz",
- "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
- "es-abstract": "^1.20.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/string.prototype.trimstart": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz",
- "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
- "es-abstract": "^1.20.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "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/strnum": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
- "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA=="
- },
- "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/text-table": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
- "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
- "dev": true
- },
- "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/ts-jest": {
- "version": "29.0.3",
- "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.3.tgz",
- "integrity": "sha512-Ibygvmuyq1qp/z3yTh9QTwVVAbFdDy/+4BtIQR2sp6baF2SJU/8CKK/hhnGIDY2L90Az2jIqTwZPnN2p+BweiQ==",
- "dev": true,
- "dependencies": {
- "bs-logger": "0.x",
- "fast-json-stable-stringify": "2.x",
- "jest-util": "^29.0.0",
- "json5": "^2.2.1",
- "lodash.memoize": "4.x",
- "make-error": "1.x",
- "semver": "7.x",
- "yargs-parser": "^21.0.1"
- },
- "bin": {
- "ts-jest": "cli.js"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- },
- "peerDependencies": {
- "@babel/core": ">=7.0.0-beta.0 <8",
- "@jest/types": "^29.0.0",
- "babel-jest": "^29.0.0",
- "jest": "^29.0.0",
- "typescript": ">=4.3"
- },
- "peerDependenciesMeta": {
- "@babel/core": {
- "optional": true
- },
- "@jest/types": {
- "optional": true
- },
- "babel-jest": {
- "optional": true
- },
- "esbuild": {
- "optional": true
- }
- }
- },
- "node_modules/ts-jest/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/ts-jest/node_modules/semver": {
- "version": "7.3.8",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
- "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
- "dev": true,
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/ts-jest/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/ts-node": {
- "version": "10.9.1",
- "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
- "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==",
- "dev": true,
- "dependencies": {
- "@cspotcode/source-map-support": "^0.8.0",
- "@tsconfig/node10": "^1.0.7",
- "@tsconfig/node12": "^1.0.7",
- "@tsconfig/node14": "^1.0.0",
- "@tsconfig/node16": "^1.0.2",
- "acorn": "^8.4.1",
- "acorn-walk": "^8.1.1",
- "arg": "^4.1.0",
- "create-require": "^1.1.0",
- "diff": "^4.0.1",
- "make-error": "^1.1.1",
- "v8-compile-cache-lib": "^3.0.1",
- "yn": "3.1.1"
- },
- "bin": {
- "ts-node": "dist/bin.js",
- "ts-node-cwd": "dist/bin-cwd.js",
- "ts-node-esm": "dist/bin-esm.js",
- "ts-node-script": "dist/bin-script.js",
- "ts-node-transpile-only": "dist/bin-transpile.js",
- "ts-script": "dist/bin-script-deprecated.js"
- },
- "peerDependencies": {
- "@swc/core": ">=1.2.50",
- "@swc/wasm": ">=1.2.50",
- "@types/node": "*",
- "typescript": ">=2.7"
- },
- "peerDependenciesMeta": {
- "@swc/core": {
- "optional": true
- },
- "@swc/wasm": {
- "optional": true
- }
- }
- },
- "node_modules/ts-node/node_modules/diff": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
- "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
- "dev": true,
- "engines": {
- "node": ">=0.3.1"
- }
- },
- "node_modules/tsconfig-paths": {
- "version": "3.14.2",
- "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz",
- "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==",
- "dev": true,
- "dependencies": {
- "@types/json5": "^0.0.29",
- "json5": "^1.0.2",
- "minimist": "^1.2.6",
- "strip-bom": "^3.0.0"
- }
- },
- "node_modules/tsconfig-paths/node_modules/json5": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
- "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
- "dev": true,
- "dependencies": {
- "minimist": "^1.2.0"
- },
- "bin": {
- "json5": "lib/cli.js"
- }
- },
- "node_modules/tsconfig-paths/node_modules/strip-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/tslib": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
- "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
- },
- "node_modules/tsutils": {
- "version": "3.21.0",
- "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
- "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
- "dev": true,
- "dependencies": {
- "tslib": "^1.8.1"
- },
- "engines": {
- "node": ">= 6"
- },
- "peerDependencies": {
- "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
- }
- },
- "node_modules/tsutils/node_modules/tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
- "dev": true
- },
- "node_modules/type-check": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
- "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
- "dev": true,
- "dependencies": {
- "prelude-ls": "^1.2.1"
- },
- "engines": {
- "node": ">= 0.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/typed-array-length": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
- "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "for-each": "^0.3.3",
- "is-typed-array": "^1.1.9"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/typescript": {
- "version": "4.9.4",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
- "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==",
- "dev": true,
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
- },
- "engines": {
- "node": ">=4.2.0"
- }
- },
- "node_modules/unbox-primitive": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
- "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "has-bigints": "^1.0.2",
- "has-symbols": "^1.0.3",
- "which-boxed-primitive": "^1.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/update-browserslist-db": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
- "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- }
- ],
- "dependencies": {
- "escalade": "^3.1.1",
- "picocolors": "^1.0.0"
- },
- "bin": {
- "browserslist-lint": "cli.js"
- },
- "peerDependencies": {
- "browserslist": ">= 4.21.0"
- }
- },
- "node_modules/uri-js": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
- "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
- "dev": true,
- "dependencies": {
- "punycode": "^2.1.0"
- }
- },
- "node_modules/uuid": {
- "version": "8.3.2",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
- "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
- "bin": {
- "uuid": "dist/bin/uuid"
- }
- },
- "node_modules/v8-compile-cache-lib": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
- "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
- "dev": true
- },
- "node_modules/v8-to-istanbul": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz",
- "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==",
- "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/which-boxed-primitive": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
- "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
- "dev": true,
- "dependencies": {
- "is-bigint": "^1.0.1",
- "is-boolean-object": "^1.1.0",
- "is-number-object": "^1.0.4",
- "is-string": "^1.0.5",
- "is-symbol": "^1.0.3"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/which-typed-array": {
- "version": "1.1.9",
- "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz",
- "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==",
- "dev": true,
- "dependencies": {
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.2",
- "for-each": "^0.3.3",
- "gopd": "^1.0.1",
- "has-tostringtag": "^1.0.0",
- "is-typed-array": "^1.1.10"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/word-wrap": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
- "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "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/xml": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz",
- "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==",
- "dev": true
- },
- "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.6.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz",
- "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==",
- "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/yn": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
- "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "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"
- }
- }
- },
- "dependencies": {
- "@ampproject/remapping": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
- "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==",
- "dev": true,
- "requires": {
- "@jridgewell/gen-mapping": "^0.1.0",
- "@jridgewell/trace-mapping": "^0.3.9"
- }
- },
- "@aws-cdk/asset-awscli-v1": {
- "version": "2.2.98",
- "resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.98.tgz",
- "integrity": "sha512-SRJeHb08wW5FVZN7OrbzHzyxW9HuRek2irRCUc+6YBgIRM1JYlyUSd+vcaPThTllNl7rUf4oNvmyK0/3tWLKDg=="
- },
- "@aws-cdk/asset-kubectl-v20": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/@aws-cdk/asset-kubectl-v20/-/asset-kubectl-v20-2.1.1.tgz",
- "integrity": "sha512-U1ntiX8XiMRRRH5J1IdC+1t5CE89015cwyt5U63Cpk0GnMlN5+h9WsWMlKlPXZR4rdq/m806JRlBMRpBUB2Dhw=="
- },
- "@aws-cdk/asset-node-proxy-agent-v5": {
- "version": "2.0.78",
- "resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v5/-/asset-node-proxy-agent-v5-2.0.78.tgz",
- "integrity": "sha512-NMGFaszbLkLQlxIJ0ydyO+P78cgTEUleGt1nn3CSRyuBHoYkHNGAcY2JUxTFhQc3/AZuq1x4w87zqh7eAOTyTw=="
- },
- "@aws-cdk/aws-lambda-python-alpha": {
- "version": "2.68.0-alpha.0",
- "resolved": "https://registry.npmjs.org/@aws-cdk/aws-lambda-python-alpha/-/aws-lambda-python-alpha-2.68.0-alpha.0.tgz",
- "integrity": "sha512-rWKI4kLIblfGXMmJ6fH07CMnktbpWqJTatP80qwbBGbLclSPwIQi4hcP2T6gMdR/1mHybR0LyXzfKON34k/KJg==",
- "requires": {}
- },
- "@aws-cdk/aws-servicecatalogappregistry-alpha": {
- "version": "2.62.2-alpha.0",
- "resolved": "https://registry.npmjs.org/@aws-cdk/aws-servicecatalogappregistry-alpha/-/aws-servicecatalogappregistry-alpha-2.62.2-alpha.0.tgz",
- "integrity": "sha512-ziMXproSFdqwpVBqVOD2vsCqqmGKxJTd9xzrT3MasCowA0M0fYUSk2IjdXvEGlRzGviCm0wjcKfrDqNIfqqXuA==",
- "requires": {}
- },
- "@aws-crypto/ie11-detection": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz",
- "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==",
- "requires": {
- "tslib": "^1.11.1"
- },
- "dependencies": {
- "tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- }
- }
- },
- "@aws-crypto/sha256-browser": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz",
- "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==",
- "requires": {
- "@aws-crypto/ie11-detection": "^3.0.0",
- "@aws-crypto/sha256-js": "^3.0.0",
- "@aws-crypto/supports-web-crypto": "^3.0.0",
- "@aws-crypto/util": "^3.0.0",
- "@aws-sdk/types": "^3.222.0",
- "@aws-sdk/util-locate-window": "^3.0.0",
- "@aws-sdk/util-utf8-browser": "^3.0.0",
- "tslib": "^1.11.1"
- },
- "dependencies": {
- "tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- }
- }
- },
- "@aws-crypto/sha256-js": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz",
- "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==",
- "requires": {
- "@aws-crypto/util": "^3.0.0",
- "@aws-sdk/types": "^3.222.0",
- "tslib": "^1.11.1"
- },
- "dependencies": {
- "tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- }
- }
- },
- "@aws-crypto/supports-web-crypto": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz",
- "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==",
- "requires": {
- "tslib": "^1.11.1"
- },
- "dependencies": {
- "tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- }
- }
- },
- "@aws-crypto/util": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz",
- "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==",
- "requires": {
- "@aws-sdk/types": "^3.222.0",
- "@aws-sdk/util-utf8-browser": "^3.0.0",
- "tslib": "^1.11.1"
- },
- "dependencies": {
- "tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
- }
- }
- },
- "@aws-sdk/abort-controller": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.295.0.tgz",
- "integrity": "sha512-uohsGotvQ8RTgVZ9sQt0y3L60jBEYgN8MOn3Seaku8HpIIo9c6iIfkF0bMXZeFI2sCxqbrBDbsPKYWxr7rd8LA==",
- "requires": {
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/client-dynamodb": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-dynamodb/-/client-dynamodb-3.295.0.tgz",
- "integrity": "sha512-upUEezK2P1c8GqwFG3h4vMXzjDHGyZvlGoiOPytrz4akmP4p120+cJjCwNFHJmG5TqSUCJUhZ/gMjF5ku1eosg==",
- "requires": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/client-sts": "3.295.0",
- "@aws-sdk/config-resolver": "3.295.0",
- "@aws-sdk/credential-provider-node": "3.295.0",
- "@aws-sdk/fetch-http-handler": "3.295.0",
- "@aws-sdk/hash-node": "3.295.0",
- "@aws-sdk/invalid-dependency": "3.295.0",
- "@aws-sdk/middleware-content-length": "3.295.0",
- "@aws-sdk/middleware-endpoint": "3.295.0",
- "@aws-sdk/middleware-endpoint-discovery": "3.295.0",
- "@aws-sdk/middleware-host-header": "3.295.0",
- "@aws-sdk/middleware-logger": "3.295.0",
- "@aws-sdk/middleware-recursion-detection": "3.295.0",
- "@aws-sdk/middleware-retry": "3.295.0",
- "@aws-sdk/middleware-serde": "3.295.0",
- "@aws-sdk/middleware-signing": "3.295.0",
- "@aws-sdk/middleware-stack": "3.295.0",
- "@aws-sdk/middleware-user-agent": "3.295.0",
- "@aws-sdk/node-config-provider": "3.295.0",
- "@aws-sdk/node-http-handler": "3.295.0",
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/smithy-client": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/url-parser": "3.295.0",
- "@aws-sdk/util-base64": "3.295.0",
- "@aws-sdk/util-body-length-browser": "3.295.0",
- "@aws-sdk/util-body-length-node": "3.295.0",
- "@aws-sdk/util-defaults-mode-browser": "3.295.0",
- "@aws-sdk/util-defaults-mode-node": "3.295.0",
- "@aws-sdk/util-endpoints": "3.295.0",
- "@aws-sdk/util-retry": "3.295.0",
- "@aws-sdk/util-user-agent-browser": "3.295.0",
- "@aws-sdk/util-user-agent-node": "3.295.0",
- "@aws-sdk/util-utf8": "3.295.0",
- "@aws-sdk/util-waiter": "3.295.0",
- "tslib": "^2.5.0",
- "uuid": "^8.3.2"
- }
- },
- "@aws-sdk/client-ec2": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-ec2/-/client-ec2-3.295.0.tgz",
- "integrity": "sha512-F2abZUElpiJvr4d5AUVODbgFPD8UMniFpAYb2Y1TruBR7d6gF9RDJ8jm5Epsg1tlL511kJBouREFID5bWQba3w==",
- "requires": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/client-sts": "3.295.0",
- "@aws-sdk/config-resolver": "3.295.0",
- "@aws-sdk/credential-provider-node": "3.295.0",
- "@aws-sdk/fetch-http-handler": "3.295.0",
- "@aws-sdk/hash-node": "3.295.0",
- "@aws-sdk/invalid-dependency": "3.295.0",
- "@aws-sdk/middleware-content-length": "3.295.0",
- "@aws-sdk/middleware-endpoint": "3.295.0",
- "@aws-sdk/middleware-host-header": "3.295.0",
- "@aws-sdk/middleware-logger": "3.295.0",
- "@aws-sdk/middleware-recursion-detection": "3.295.0",
- "@aws-sdk/middleware-retry": "3.295.0",
- "@aws-sdk/middleware-sdk-ec2": "3.295.0",
- "@aws-sdk/middleware-serde": "3.295.0",
- "@aws-sdk/middleware-signing": "3.295.0",
- "@aws-sdk/middleware-stack": "3.295.0",
- "@aws-sdk/middleware-user-agent": "3.295.0",
- "@aws-sdk/node-config-provider": "3.295.0",
- "@aws-sdk/node-http-handler": "3.295.0",
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/smithy-client": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/url-parser": "3.295.0",
- "@aws-sdk/util-base64": "3.295.0",
- "@aws-sdk/util-body-length-browser": "3.295.0",
- "@aws-sdk/util-body-length-node": "3.295.0",
- "@aws-sdk/util-defaults-mode-browser": "3.295.0",
- "@aws-sdk/util-defaults-mode-node": "3.295.0",
- "@aws-sdk/util-endpoints": "3.295.0",
- "@aws-sdk/util-retry": "3.295.0",
- "@aws-sdk/util-user-agent-browser": "3.295.0",
- "@aws-sdk/util-user-agent-node": "3.295.0",
- "@aws-sdk/util-utf8": "3.295.0",
- "@aws-sdk/util-waiter": "3.295.0",
- "fast-xml-parser": "4.1.2",
- "tslib": "^2.5.0",
- "uuid": "^8.3.2"
- }
- },
- "@aws-sdk/client-rds": {
- "version": "3.314.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-rds/-/client-rds-3.314.0.tgz",
- "integrity": "sha512-+jvimITTzmDkMNwAh2vV4+r22GZWF1TCdCiQqB1+djApmfifUFSEGyDrNRpHOKYeBhDR6mHPVC+qW5hs8XWr6A==",
- "requires": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/client-sts": "3.312.0",
- "@aws-sdk/config-resolver": "3.310.0",
- "@aws-sdk/credential-provider-node": "3.310.0",
- "@aws-sdk/fetch-http-handler": "3.310.0",
- "@aws-sdk/hash-node": "3.310.0",
- "@aws-sdk/invalid-dependency": "3.310.0",
- "@aws-sdk/middleware-content-length": "3.310.0",
- "@aws-sdk/middleware-endpoint": "3.310.0",
- "@aws-sdk/middleware-host-header": "3.310.0",
- "@aws-sdk/middleware-logger": "3.310.0",
- "@aws-sdk/middleware-recursion-detection": "3.310.0",
- "@aws-sdk/middleware-retry": "3.310.0",
- "@aws-sdk/middleware-sdk-rds": "3.310.0",
- "@aws-sdk/middleware-serde": "3.310.0",
- "@aws-sdk/middleware-signing": "3.310.0",
- "@aws-sdk/middleware-stack": "3.310.0",
- "@aws-sdk/middleware-user-agent": "3.310.0",
- "@aws-sdk/node-config-provider": "3.310.0",
- "@aws-sdk/node-http-handler": "3.310.0",
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/smithy-client": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/url-parser": "3.310.0",
- "@aws-sdk/util-base64": "3.310.0",
- "@aws-sdk/util-body-length-browser": "3.310.0",
- "@aws-sdk/util-body-length-node": "3.310.0",
- "@aws-sdk/util-defaults-mode-browser": "3.310.0",
- "@aws-sdk/util-defaults-mode-node": "3.310.0",
- "@aws-sdk/util-endpoints": "3.310.0",
- "@aws-sdk/util-retry": "3.310.0",
- "@aws-sdk/util-user-agent-browser": "3.310.0",
- "@aws-sdk/util-user-agent-node": "3.310.0",
- "@aws-sdk/util-utf8": "3.310.0",
- "@aws-sdk/util-waiter": "3.310.0",
- "fast-xml-parser": "4.1.2",
- "tslib": "^2.5.0"
- },
- "dependencies": {
- "@aws-sdk/abort-controller": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.310.0.tgz",
- "integrity": "sha512-v1zrRQxDLA1MdPim159Vx/CPHqsB4uybSxRi1CnfHO5ZjHryx3a5htW2gdGAykVCul40+yJXvfpufMrELVxH+g==",
- "requires": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/client-sso": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.310.0.tgz",
- "integrity": "sha512-netFap3Mp9I7bzAjsswHPA5WEbQtNMmXvW9/IVb7tmf85/esXCWindtyI43e/Xerut9ZVyEACPBFn30CLLE2xQ==",
- "requires": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/config-resolver": "3.310.0",
- "@aws-sdk/fetch-http-handler": "3.310.0",
- "@aws-sdk/hash-node": "3.310.0",
- "@aws-sdk/invalid-dependency": "3.310.0",
- "@aws-sdk/middleware-content-length": "3.310.0",
- "@aws-sdk/middleware-endpoint": "3.310.0",
- "@aws-sdk/middleware-host-header": "3.310.0",
- "@aws-sdk/middleware-logger": "3.310.0",
- "@aws-sdk/middleware-recursion-detection": "3.310.0",
- "@aws-sdk/middleware-retry": "3.310.0",
- "@aws-sdk/middleware-serde": "3.310.0",
- "@aws-sdk/middleware-stack": "3.310.0",
- "@aws-sdk/middleware-user-agent": "3.310.0",
- "@aws-sdk/node-config-provider": "3.310.0",
- "@aws-sdk/node-http-handler": "3.310.0",
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/smithy-client": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/url-parser": "3.310.0",
- "@aws-sdk/util-base64": "3.310.0",
- "@aws-sdk/util-body-length-browser": "3.310.0",
- "@aws-sdk/util-body-length-node": "3.310.0",
- "@aws-sdk/util-defaults-mode-browser": "3.310.0",
- "@aws-sdk/util-defaults-mode-node": "3.310.0",
- "@aws-sdk/util-endpoints": "3.310.0",
- "@aws-sdk/util-retry": "3.310.0",
- "@aws-sdk/util-user-agent-browser": "3.310.0",
- "@aws-sdk/util-user-agent-node": "3.310.0",
- "@aws-sdk/util-utf8": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/client-sso-oidc": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.310.0.tgz",
- "integrity": "sha512-3GKaRSfMD3OiYWGa+qg5KvJw0nLV0Vu7zRiulLuKDvgmWw3SNJKn3frWlmq/bKFUKahLsV8zozbeJItxtKAD6g==",
- "requires": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/config-resolver": "3.310.0",
- "@aws-sdk/fetch-http-handler": "3.310.0",
- "@aws-sdk/hash-node": "3.310.0",
- "@aws-sdk/invalid-dependency": "3.310.0",
- "@aws-sdk/middleware-content-length": "3.310.0",
- "@aws-sdk/middleware-endpoint": "3.310.0",
- "@aws-sdk/middleware-host-header": "3.310.0",
- "@aws-sdk/middleware-logger": "3.310.0",
- "@aws-sdk/middleware-recursion-detection": "3.310.0",
- "@aws-sdk/middleware-retry": "3.310.0",
- "@aws-sdk/middleware-serde": "3.310.0",
- "@aws-sdk/middleware-stack": "3.310.0",
- "@aws-sdk/middleware-user-agent": "3.310.0",
- "@aws-sdk/node-config-provider": "3.310.0",
- "@aws-sdk/node-http-handler": "3.310.0",
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/smithy-client": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/url-parser": "3.310.0",
- "@aws-sdk/util-base64": "3.310.0",
- "@aws-sdk/util-body-length-browser": "3.310.0",
- "@aws-sdk/util-body-length-node": "3.310.0",
- "@aws-sdk/util-defaults-mode-browser": "3.310.0",
- "@aws-sdk/util-defaults-mode-node": "3.310.0",
- "@aws-sdk/util-endpoints": "3.310.0",
- "@aws-sdk/util-retry": "3.310.0",
- "@aws-sdk/util-user-agent-browser": "3.310.0",
- "@aws-sdk/util-user-agent-node": "3.310.0",
- "@aws-sdk/util-utf8": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/client-sts": {
- "version": "3.312.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.312.0.tgz",
- "integrity": "sha512-t0U7vRvWaMjrzBUo6tPrHe6HE97Blqx+b4GOjFbcbLtzxLlcRfhnWJik0Lp8hJtVqzNoN5mL4OeYgK7CRpL/Sw==",
- "requires": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/config-resolver": "3.310.0",
- "@aws-sdk/credential-provider-node": "3.310.0",
- "@aws-sdk/fetch-http-handler": "3.310.0",
- "@aws-sdk/hash-node": "3.310.0",
- "@aws-sdk/invalid-dependency": "3.310.0",
- "@aws-sdk/middleware-content-length": "3.310.0",
- "@aws-sdk/middleware-endpoint": "3.310.0",
- "@aws-sdk/middleware-host-header": "3.310.0",
- "@aws-sdk/middleware-logger": "3.310.0",
- "@aws-sdk/middleware-recursion-detection": "3.310.0",
- "@aws-sdk/middleware-retry": "3.310.0",
- "@aws-sdk/middleware-sdk-sts": "3.310.0",
- "@aws-sdk/middleware-serde": "3.310.0",
- "@aws-sdk/middleware-signing": "3.310.0",
- "@aws-sdk/middleware-stack": "3.310.0",
- "@aws-sdk/middleware-user-agent": "3.310.0",
- "@aws-sdk/node-config-provider": "3.310.0",
- "@aws-sdk/node-http-handler": "3.310.0",
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/smithy-client": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/url-parser": "3.310.0",
- "@aws-sdk/util-base64": "3.310.0",
- "@aws-sdk/util-body-length-browser": "3.310.0",
- "@aws-sdk/util-body-length-node": "3.310.0",
- "@aws-sdk/util-defaults-mode-browser": "3.310.0",
- "@aws-sdk/util-defaults-mode-node": "3.310.0",
- "@aws-sdk/util-endpoints": "3.310.0",
- "@aws-sdk/util-retry": "3.310.0",
- "@aws-sdk/util-user-agent-browser": "3.310.0",
- "@aws-sdk/util-user-agent-node": "3.310.0",
- "@aws-sdk/util-utf8": "3.310.0",
- "fast-xml-parser": "4.1.2",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/config-resolver": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.310.0.tgz",
- "integrity": "sha512-8vsT+/50lOqfDxka9m/rRt6oxv1WuGZoP8oPMk0Dt+TxXMbAzf4+rejBgiB96wshI1k3gLokYRjSQZn+dDtT8g==",
- "requires": {
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/util-config-provider": "3.310.0",
- "@aws-sdk/util-middleware": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/credential-provider-env": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.310.0.tgz",
- "integrity": "sha512-vvIPQpI16fj95xwS7M3D48F7QhZJBnnCgB5lR+b7So+vsG9ibm1mZRVGzVpdxCvgyOhHFbvrby9aalNJmmIP1A==",
- "requires": {
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/credential-provider-imds": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.310.0.tgz",
- "integrity": "sha512-baxK7Zp6dai5AGW01FIW27xS2KAaPUmKLIXv5SvFYsUgXXvNW55im4uG3b+2gA0F7V+hXvVBH08OEqmwW6we5w==",
- "requires": {
- "@aws-sdk/node-config-provider": "3.310.0",
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/url-parser": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/credential-provider-ini": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.310.0.tgz",
- "integrity": "sha512-gtRz7I+4BBpwZ3tc6UIt5lQuiAFnkpOibxHh95x1M6HDxBjm+uqD6RPZYVH+dULZPYXOtOTsHV0IGjrcV0sSRg==",
- "requires": {
- "@aws-sdk/credential-provider-env": "3.310.0",
- "@aws-sdk/credential-provider-imds": "3.310.0",
- "@aws-sdk/credential-provider-process": "3.310.0",
- "@aws-sdk/credential-provider-sso": "3.310.0",
- "@aws-sdk/credential-provider-web-identity": "3.310.0",
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/shared-ini-file-loader": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/credential-provider-node": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.310.0.tgz",
- "integrity": "sha512-FrOztUcOq2Sp32xGtJvxfvdlmuAeoxIu/AElHzV1bkx6Pzo9DkQBhXrSQ+JFSpI++weOD4ZGFhAvgbgUOT4VAg==",
- "requires": {
- "@aws-sdk/credential-provider-env": "3.310.0",
- "@aws-sdk/credential-provider-imds": "3.310.0",
- "@aws-sdk/credential-provider-ini": "3.310.0",
- "@aws-sdk/credential-provider-process": "3.310.0",
- "@aws-sdk/credential-provider-sso": "3.310.0",
- "@aws-sdk/credential-provider-web-identity": "3.310.0",
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/shared-ini-file-loader": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/credential-provider-process": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.310.0.tgz",
- "integrity": "sha512-h73sg6GPMUWC+3zMCbA1nZ2O03nNJt7G96JdmnantiXBwHpRKWW8nBTLzx5uhXn6hTuTaoQRP/P+oxQJKYdMmA==",
- "requires": {
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/shared-ini-file-loader": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/credential-provider-sso": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.310.0.tgz",
- "integrity": "sha512-nXkpT8mrM/wRqSiz/a4p9U2UrOKyfZXhbPHIHyQj8K+uLjsYS+WPuH287J4A5Q57A6uarTrj5RjHmVeZVLaHmg==",
- "requires": {
- "@aws-sdk/client-sso": "3.310.0",
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/shared-ini-file-loader": "3.310.0",
- "@aws-sdk/token-providers": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/credential-provider-web-identity": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.310.0.tgz",
- "integrity": "sha512-H4SzuZXILNhK6/IR1uVvsUDZvzc051hem7GLyYghBCu8mU+tq28YhKE8MfSroi6eL2e5Vujloij1OM2EQQkPkw==",
- "requires": {
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/fetch-http-handler": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.310.0.tgz",
- "integrity": "sha512-Bi9vIwzdkw1zMcvi/zGzlWS9KfIEnAq4NNhsnCxbQ4OoIRU9wvU+WGZdBBhxg0ZxZmpp1j1aZhU53lLjA07MHw==",
- "requires": {
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/querystring-builder": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/util-base64": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/hash-node": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.310.0.tgz",
- "integrity": "sha512-NvE2fhRc8GRwCXBfDehxVAWCmVwVMILliAKVPAEr4yz2CkYs0tqU51S48x23dtna07H4qHtgpeNqVTthcIQOEQ==",
- "requires": {
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/util-buffer-from": "3.310.0",
- "@aws-sdk/util-utf8": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/invalid-dependency": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.310.0.tgz",
- "integrity": "sha512-1s5RG5rSPXoa/aZ/Kqr5U/7lqpx+Ry81GprQ2bxWqJvWQIJ0IRUwo5pk8XFxbKVr/2a+4lZT/c3OGoBOM1yRRA==",
- "requires": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/is-array-buffer": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.310.0.tgz",
- "integrity": "sha512-urnbcCR+h9NWUnmOtet/s4ghvzsidFmspfhYaHAmSRdy9yDjdjBJMFjjsn85A1ODUktztm+cVncXjQ38WCMjMQ==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-content-length": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.310.0.tgz",
- "integrity": "sha512-P8tQZxgDt6CAh1wd/W6WPzjc+uWPJwQkm+F7rAwRlM+k9q17HrhnksGDKcpuuLyIhPQYdmOMIkpKVgXGa4avhQ==",
- "requires": {
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-endpoint": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.310.0.tgz",
- "integrity": "sha512-Z+N2vOL8K354/lstkClxLLsr6hCpVRh+0tCMXrVj66/NtKysCEZ/0b9LmqOwD9pWHNiI2mJqXwY0gxNlKAroUg==",
- "requires": {
- "@aws-sdk/middleware-serde": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/url-parser": "3.310.0",
- "@aws-sdk/util-middleware": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-host-header": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.310.0.tgz",
- "integrity": "sha512-QWSA+46/hXorXyWa61ic2K7qZzwHTiwfk2e9mRRjeIRepUgI3qxFjsYqrWtrOGBjmFmq0pYIY8Bb/DCJuQqcoA==",
- "requires": {
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-logger": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.310.0.tgz",
- "integrity": "sha512-Lurm8XofrASBRnAVtiSNuDSRsRqPNg27RIFLLsLp/pqog9nFJ0vz0kgdb9S5Z+zw83Mm+UlqOe6D8NTUNp4fVg==",
- "requires": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-recursion-detection": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.310.0.tgz",
- "integrity": "sha512-SuB75/xk/gyue24gkriTwO2jFd7YcUGZDClQYuRejgbXSa3CO0lWyawQtfLcSSEBp9izrEVXuFH24K1eAft5nQ==",
- "requires": {
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-retry": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.310.0.tgz",
- "integrity": "sha512-oTPsRy2W4s+dfxbJPW7Km+hHtv/OMsNsVfThAq8DDYKC13qlr1aAyOqGLD+dpBy2aKe7ss517Sy2HcHtHqm7/g==",
- "requires": {
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/service-error-classification": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/util-middleware": "3.310.0",
- "@aws-sdk/util-retry": "3.310.0",
- "tslib": "^2.5.0",
- "uuid": "^8.3.2"
- }
- },
- "@aws-sdk/middleware-sdk-sts": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.310.0.tgz",
- "integrity": "sha512-+5PFwlYNLvLLIfw0ASAoWV/iIF8Zv6R6QGtyP0CclhRSvNjgbQDVnV0g95MC5qvh+GB/Yjlkt8qAjLSPjHfsrQ==",
- "requires": {
- "@aws-sdk/middleware-signing": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-serde": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.310.0.tgz",
- "integrity": "sha512-RNeeTVWSLTaentUeCgQKZhAl+C6hxtwD78cQWS10UymWpQFwbaxztzKUu4UQS5xA2j6PxwPRRUjqa4jcFjfLsg==",
- "requires": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-signing": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.310.0.tgz",
- "integrity": "sha512-f9mKq+XMdW207Af3hKjdTnpNhdtwqWuvFs/ZyXoOkp/g1MY1O6L23Jy6i52m29LxbT4AuNRG1oKODfXM0vYVjQ==",
- "requires": {
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/signature-v4": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/util-middleware": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-stack": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.310.0.tgz",
- "integrity": "sha512-010O1PD+UAcZVKRvqEusE1KJqN96wwrf6QsqbRM0ywsKQ21NDweaHvEDlds2VHpgmofxkRLRu/IDrlPkKRQrRg==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-user-agent": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.310.0.tgz",
- "integrity": "sha512-x3IOwSwSbwKidlxRk3CNVHVUb06SRuaELxggCaR++QVI8NU6qD/l4VHXKVRvbTHiC/cYxXE/GaBDgQVpDR7V/g==",
- "requires": {
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/util-endpoints": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/node-config-provider": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.310.0.tgz",
- "integrity": "sha512-T/Pp6htc6hq/Cq+MLNDSyiwWCMVF6GqbBbXKVlO5L8rdHx4sq9xPdoPveZhGWrxvkanjA6eCwUp6E0riBOSVng==",
- "requires": {
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/shared-ini-file-loader": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/node-http-handler": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.310.0.tgz",
- "integrity": "sha512-irv9mbcM9xC2xYjArQF5SYmHBMu4ciMWtGsoHII1nRuFOl9FoT4ffTvEPuLlfC6pznzvKt9zvnm6xXj7gDChKg==",
- "requires": {
- "@aws-sdk/abort-controller": "3.310.0",
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/querystring-builder": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/property-provider": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.310.0.tgz",
- "integrity": "sha512-3lxDb0akV6BBzmFe4nLPaoliQbAifyWJhuvuDOu7e8NzouvpQXs0275w9LePhhcgjKAEVXUIse05ZW2DLbxo/g==",
- "requires": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/protocol-http": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.310.0.tgz",
- "integrity": "sha512-fgZ1aw/irQtnrsR58pS8ThKOWo57Py3xX6giRvwSgZDEcxHfVzuQjy9yPuV++v04fdmdtgpbGf8WfvAAJ11yXQ==",
- "requires": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/querystring-builder": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.310.0.tgz",
- "integrity": "sha512-ZHH8GV/80+pWGo7DzsvwvXR5xVxUHXUvPJPFAkhr6nCf78igdoF8gR10ScFoEKbtEapoNTaZlKHPXxpD8aPG7A==",
- "requires": {
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/util-uri-escape": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/querystring-parser": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.310.0.tgz",
- "integrity": "sha512-YkIznoP6lsiIUHinx++/lbb3tlMURGGqMpo0Pnn32zYzGrJXA6eC3D0as2EcMjo55onTfuLcIiX4qzXes2MYOA==",
- "requires": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/service-error-classification": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.310.0.tgz",
- "integrity": "sha512-PuyC7k3qfIKeH2LCnDwbttMOKq3qAx4buvg0yfnJtQOz6t1AR8gsnAq0CjKXXyfkXwNKWTqCpE6lVNUIkXgsMw=="
- },
- "@aws-sdk/shared-ini-file-loader": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.310.0.tgz",
- "integrity": "sha512-N0q9pG0xSjQwc690YQND5bofm+4nfUviQ/Ppgan2kU6aU0WUq8KwgHJBto/YEEI+VlrME30jZJnxtOvcZJc2XA==",
- "requires": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/signature-v4": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.310.0.tgz",
- "integrity": "sha512-1M60P1ZBNAjCFv9sYW29OF6okktaeibWyW3lMXqzoHF70lHBZh+838iUchznXUA5FLabfn4jBFWMRxlAXJUY2Q==",
- "requires": {
- "@aws-sdk/is-array-buffer": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/util-hex-encoding": "3.310.0",
- "@aws-sdk/util-middleware": "3.310.0",
- "@aws-sdk/util-uri-escape": "3.310.0",
- "@aws-sdk/util-utf8": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/smithy-client": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.310.0.tgz",
- "integrity": "sha512-UHMFvhoB2RLzsTb0mQe1ofvBUg/+/JEu1uptavxf/hEpEKZnRAaHH5FNkTG+mbFd/olay/QFjqNcMD6t8LcsNQ==",
- "requires": {
- "@aws-sdk/middleware-stack": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/token-providers": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.310.0.tgz",
- "integrity": "sha512-G1JvB+2v8k900VJFkKVQXgLGF50ShOEIPxfK1gSQLkSU85vPwGIAANs1KvnlW08FsNbWp3+sKca4kfYKsooXMw==",
- "requires": {
- "@aws-sdk/client-sso-oidc": "3.310.0",
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/shared-ini-file-loader": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/types": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.310.0.tgz",
- "integrity": "sha512-j8eamQJ7YcIhw7fneUfs8LYl3t01k4uHi4ZDmNRgtbmbmTTG3FZc2MotStZnp3nZB6vLiPF1o5aoJxWVvkzS6A==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/url-parser": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.310.0.tgz",
- "integrity": "sha512-mCLnCaSB9rQvAgx33u0DujLvr4d5yEm/W5r789GblwwQnlNXedVu50QRizMLTpltYWyAUoXjJgQnJHmJMaKXhw==",
- "requires": {
- "@aws-sdk/querystring-parser": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-base64": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64/-/util-base64-3.310.0.tgz",
- "integrity": "sha512-v3+HBKQvqgdzcbL+pFswlx5HQsd9L6ZTlyPVL2LS9nNXnCcR3XgGz9jRskikRUuUvUXtkSG1J88GAOnJ/apTPg==",
- "requires": {
- "@aws-sdk/util-buffer-from": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-body-length-browser": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.310.0.tgz",
- "integrity": "sha512-sxsC3lPBGfpHtNTUoGXMQXLwjmR0zVpx0rSvzTPAuoVILVsp5AU/w5FphNPxD5OVIjNbZv9KsKTuvNTiZjDp9g==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-body-length-node": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-node/-/util-body-length-node-3.310.0.tgz",
- "integrity": "sha512-2tqGXdyKhyA6w4zz7UPoS8Ip+7sayOg9BwHNidiGm2ikbDxm1YrCfYXvCBdwaJxa4hJfRVz+aL9e+d3GqPI9pQ==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-buffer-from": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.310.0.tgz",
- "integrity": "sha512-i6LVeXFtGih5Zs8enLrt+ExXY92QV25jtEnTKHsmlFqFAuL3VBeod6boeMXkN2p9lbSVVQ1sAOOYZOHYbYkntw==",
- "requires": {
- "@aws-sdk/is-array-buffer": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-config-provider": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-config-provider/-/util-config-provider-3.310.0.tgz",
- "integrity": "sha512-xIBaYo8dwiojCw8vnUcIL4Z5tyfb1v3yjqyJKJWV/dqKUFOOS0U591plmXbM+M/QkXyML3ypon1f8+BoaDExrg==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-defaults-mode-browser": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.310.0.tgz",
- "integrity": "sha512-Mr2AoQsjAYNM5oAS2YJlYJqhiCvkFV/hu48slOZgbY4G7ueW4cM0DPkR16wqjcRCGqZ4JmAZB8Q5R0DMrLjhOQ==",
- "requires": {
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "bowser": "^2.11.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-defaults-mode-node": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.310.0.tgz",
- "integrity": "sha512-JyBlvhQGR8w8NpFRZZXRVTDesafFKTu/gTWjcoxP7twa+fYHSIgPPFGnlcJ/iHaucjamSaWi5EQ+YQmnSZ8yHA==",
- "requires": {
- "@aws-sdk/config-resolver": "3.310.0",
- "@aws-sdk/credential-provider-imds": "3.310.0",
- "@aws-sdk/node-config-provider": "3.310.0",
- "@aws-sdk/property-provider": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-endpoints": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.310.0.tgz",
- "integrity": "sha512-zG+/d/O5KPmAaeOMPd6bW1abifdT0H03f42keLjYEoRZzYtHPC5DuPE0UayiWGckI6BCDgy0sRKXCYS49UNFaQ==",
- "requires": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-hex-encoding": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.310.0.tgz",
- "integrity": "sha512-sVN7mcCCDSJ67pI1ZMtk84SKGqyix6/0A1Ab163YKn+lFBQRMKexleZzpYzNGxYzmQS6VanP/cfU7NiLQOaSfA==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-middleware": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.310.0.tgz",
- "integrity": "sha512-FTSUKL/eRb9X6uEZClrTe27QFXUNNp7fxYrPndZwk1hlaOP5ix+MIHBcI7pIiiY/JPfOUmPyZOu+HetlFXjWog==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-retry": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-retry/-/util-retry-3.310.0.tgz",
- "integrity": "sha512-FwWGhCBLfoivTMUHu1LIn4NjrN9JLJ/aX5aZmbcPIOhZVFJj638j0qDgZXyfvVqBuBZh7M8kGq0Oahy3dp69OA==",
- "requires": {
- "@aws-sdk/service-error-classification": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-uri-escape": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.310.0.tgz",
- "integrity": "sha512-drzt+aB2qo2LgtDoiy/3sVG8w63cgLkqFIa2NFlGpUgHFWTXkqtbgf4L5QdjRGKWhmZsnqkbtL7vkSWEcYDJ4Q==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-user-agent-browser": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.310.0.tgz",
- "integrity": "sha512-yU/4QnHHuQ5z3vsUqMQVfYLbZGYwpYblPiuZx4Zo9+x0PBkNjYMqctdDcrpoH9Z2xZiDN16AmQGK1tix117ZKw==",
- "requires": {
- "@aws-sdk/types": "3.310.0",
- "bowser": "^2.11.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-user-agent-node": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.310.0.tgz",
- "integrity": "sha512-Ra3pEl+Gn2BpeE7KiDGpi4zj7WJXZA5GXnGo3mjbi9+Y3zrbuhJAbdZO3mO/o7xDgMC6ph4xCTbaSGzU6b6EDg==",
- "requires": {
- "@aws-sdk/node-config-provider": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-utf8": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8/-/util-utf8-3.310.0.tgz",
- "integrity": "sha512-DnLfFT8uCO22uOJc0pt0DsSNau1GTisngBCDw8jQuWT5CqogMJu4b/uXmwEqfj8B3GX6Xsz8zOd6JpRlPftQoA==",
- "requires": {
- "@aws-sdk/util-buffer-from": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-waiter": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-waiter/-/util-waiter-3.310.0.tgz",
- "integrity": "sha512-AV5j3guH/Y4REu+Qh3eXQU9igljHuU4XjX2sADAgf54C0kkhcCCkkiuzk3IsX089nyJCqIcj5idbjdvpnH88Vw==",
- "requires": {
- "@aws-sdk/abort-controller": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- }
- }
- },
- "@aws-sdk/client-sso": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.295.0.tgz",
- "integrity": "sha512-uNEchm1LAQHP2/S21jz0NxCe8yqUe3J1jZG3N/dwx7uKVndHomTmjBsClGxT8IL9hC/Xl57G+fEpTCrFMjUR2g==",
- "requires": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/config-resolver": "3.295.0",
- "@aws-sdk/fetch-http-handler": "3.295.0",
- "@aws-sdk/hash-node": "3.295.0",
- "@aws-sdk/invalid-dependency": "3.295.0",
- "@aws-sdk/middleware-content-length": "3.295.0",
- "@aws-sdk/middleware-endpoint": "3.295.0",
- "@aws-sdk/middleware-host-header": "3.295.0",
- "@aws-sdk/middleware-logger": "3.295.0",
- "@aws-sdk/middleware-recursion-detection": "3.295.0",
- "@aws-sdk/middleware-retry": "3.295.0",
- "@aws-sdk/middleware-serde": "3.295.0",
- "@aws-sdk/middleware-stack": "3.295.0",
- "@aws-sdk/middleware-user-agent": "3.295.0",
- "@aws-sdk/node-config-provider": "3.295.0",
- "@aws-sdk/node-http-handler": "3.295.0",
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/smithy-client": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/url-parser": "3.295.0",
- "@aws-sdk/util-base64": "3.295.0",
- "@aws-sdk/util-body-length-browser": "3.295.0",
- "@aws-sdk/util-body-length-node": "3.295.0",
- "@aws-sdk/util-defaults-mode-browser": "3.295.0",
- "@aws-sdk/util-defaults-mode-node": "3.295.0",
- "@aws-sdk/util-endpoints": "3.295.0",
- "@aws-sdk/util-retry": "3.295.0",
- "@aws-sdk/util-user-agent-browser": "3.295.0",
- "@aws-sdk/util-user-agent-node": "3.295.0",
- "@aws-sdk/util-utf8": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/client-sso-oidc": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.295.0.tgz",
- "integrity": "sha512-HijuG2OAmTy0Wa3JHgIMBrBlsWC6GjWkH8KcRIGbFUH2nW8LFh3gBKuB1oubZ4wAdOIBFNECWA6FKFayFlKmew==",
- "requires": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/config-resolver": "3.295.0",
- "@aws-sdk/fetch-http-handler": "3.295.0",
- "@aws-sdk/hash-node": "3.295.0",
- "@aws-sdk/invalid-dependency": "3.295.0",
- "@aws-sdk/middleware-content-length": "3.295.0",
- "@aws-sdk/middleware-endpoint": "3.295.0",
- "@aws-sdk/middleware-host-header": "3.295.0",
- "@aws-sdk/middleware-logger": "3.295.0",
- "@aws-sdk/middleware-recursion-detection": "3.295.0",
- "@aws-sdk/middleware-retry": "3.295.0",
- "@aws-sdk/middleware-serde": "3.295.0",
- "@aws-sdk/middleware-stack": "3.295.0",
- "@aws-sdk/middleware-user-agent": "3.295.0",
- "@aws-sdk/node-config-provider": "3.295.0",
- "@aws-sdk/node-http-handler": "3.295.0",
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/smithy-client": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/url-parser": "3.295.0",
- "@aws-sdk/util-base64": "3.295.0",
- "@aws-sdk/util-body-length-browser": "3.295.0",
- "@aws-sdk/util-body-length-node": "3.295.0",
- "@aws-sdk/util-defaults-mode-browser": "3.295.0",
- "@aws-sdk/util-defaults-mode-node": "3.295.0",
- "@aws-sdk/util-endpoints": "3.295.0",
- "@aws-sdk/util-retry": "3.295.0",
- "@aws-sdk/util-user-agent-browser": "3.295.0",
- "@aws-sdk/util-user-agent-node": "3.295.0",
- "@aws-sdk/util-utf8": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/client-sts": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.295.0.tgz",
- "integrity": "sha512-KrLnG5EcXvry9tmsTAONhlj60F0+Z7P2PtT0XDsS8pLayHAtd9lKXsf14DOSQa9+LbPLMFbfLbuSwvPYvgxMzg==",
- "requires": {
- "@aws-crypto/sha256-browser": "3.0.0",
- "@aws-crypto/sha256-js": "3.0.0",
- "@aws-sdk/config-resolver": "3.295.0",
- "@aws-sdk/credential-provider-node": "3.295.0",
- "@aws-sdk/fetch-http-handler": "3.295.0",
- "@aws-sdk/hash-node": "3.295.0",
- "@aws-sdk/invalid-dependency": "3.295.0",
- "@aws-sdk/middleware-content-length": "3.295.0",
- "@aws-sdk/middleware-endpoint": "3.295.0",
- "@aws-sdk/middleware-host-header": "3.295.0",
- "@aws-sdk/middleware-logger": "3.295.0",
- "@aws-sdk/middleware-recursion-detection": "3.295.0",
- "@aws-sdk/middleware-retry": "3.295.0",
- "@aws-sdk/middleware-sdk-sts": "3.295.0",
- "@aws-sdk/middleware-serde": "3.295.0",
- "@aws-sdk/middleware-signing": "3.295.0",
- "@aws-sdk/middleware-stack": "3.295.0",
- "@aws-sdk/middleware-user-agent": "3.295.0",
- "@aws-sdk/node-config-provider": "3.295.0",
- "@aws-sdk/node-http-handler": "3.295.0",
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/smithy-client": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/url-parser": "3.295.0",
- "@aws-sdk/util-base64": "3.295.0",
- "@aws-sdk/util-body-length-browser": "3.295.0",
- "@aws-sdk/util-body-length-node": "3.295.0",
- "@aws-sdk/util-defaults-mode-browser": "3.295.0",
- "@aws-sdk/util-defaults-mode-node": "3.295.0",
- "@aws-sdk/util-endpoints": "3.295.0",
- "@aws-sdk/util-retry": "3.295.0",
- "@aws-sdk/util-user-agent-browser": "3.295.0",
- "@aws-sdk/util-user-agent-node": "3.295.0",
- "@aws-sdk/util-utf8": "3.295.0",
- "fast-xml-parser": "4.1.2",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/config-resolver": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.295.0.tgz",
- "integrity": "sha512-oSGdGAjmOesxGAT/Ce8P7Gdvf4KVQjasKqmlAMTXsUBxh8Mx8BQH9V3UCiCdfJ2Vx7H4pqN4Y8WcAQkje4uvbQ==",
- "requires": {
- "@aws-sdk/signature-v4": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/util-config-provider": "3.295.0",
- "@aws-sdk/util-middleware": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/credential-provider-env": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.295.0.tgz",
- "integrity": "sha512-YjUDJwhgwUgFYT4fJQVCMA1Abw2Jw1xC3EeNxeV2L54CvM9PlbFuRa5qJehePKoTLyva4bjLsMXsensXrEEIGQ==",
- "requires": {
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/credential-provider-imds": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.295.0.tgz",
- "integrity": "sha512-+tOVCZi7LUG2pvjK9P35hhXL1cZTJsbGtrMsIxrlUODjKEhht4RSiQH7zT324x6MkYby9iLjU4SUejyKBKDhYQ==",
- "requires": {
- "@aws-sdk/node-config-provider": "3.295.0",
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/url-parser": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/credential-provider-ini": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.295.0.tgz",
- "integrity": "sha512-XU3UqVVxxjyXcZ2Wkx3CM+/eLUM/EDlqJkLU6nl3FDGzPZeXC3G9Z9ZywGBo7dpRbBpDfpzSSukJisiGLTwg2w==",
- "requires": {
- "@aws-sdk/credential-provider-env": "3.295.0",
- "@aws-sdk/credential-provider-imds": "3.295.0",
- "@aws-sdk/credential-provider-process": "3.295.0",
- "@aws-sdk/credential-provider-sso": "3.295.0",
- "@aws-sdk/credential-provider-web-identity": "3.295.0",
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/shared-ini-file-loader": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/credential-provider-node": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.295.0.tgz",
- "integrity": "sha512-dU+nDJJKCyx/YBKeGgSuFM1okdoNVGWLTzrkPohPGy5+KnPaFCscrqRe2ni0ihQscguwSFXygV5SQoYNp1FGwA==",
- "requires": {
- "@aws-sdk/credential-provider-env": "3.295.0",
- "@aws-sdk/credential-provider-imds": "3.295.0",
- "@aws-sdk/credential-provider-ini": "3.295.0",
- "@aws-sdk/credential-provider-process": "3.295.0",
- "@aws-sdk/credential-provider-sso": "3.295.0",
- "@aws-sdk/credential-provider-web-identity": "3.295.0",
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/shared-ini-file-loader": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/credential-provider-process": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.295.0.tgz",
- "integrity": "sha512-efA41QAcKlb/hbDZVXnUApMPjOnu8Zj58o0WqHAdcpu7qSDzZdsmJ6dqknAbj14cyDjzXaexuN+wubGUAL9IoQ==",
- "requires": {
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/shared-ini-file-loader": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/credential-provider-sso": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.295.0.tgz",
- "integrity": "sha512-cJoCLbg3ud3/NK7otcBHkRaPvdsVEyX9tryLIPuj8rgagFWneexVh4Kzs9k+PtRN764TjVFzITw99LxBf0fe1w==",
- "requires": {
- "@aws-sdk/client-sso": "3.295.0",
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/shared-ini-file-loader": "3.295.0",
- "@aws-sdk/token-providers": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/credential-provider-web-identity": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.295.0.tgz",
- "integrity": "sha512-rBDhRYh4PiOnvz0M7AbYZZCiaPm5JDkM0xzGHEKKiW/A1wS2Gd2qbyEIK4APQ7vZMX+IJaSBBabfqm+vX5Y1kw==",
- "requires": {
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/endpoint-cache": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/endpoint-cache/-/endpoint-cache-3.295.0.tgz",
- "integrity": "sha512-81wVPETzx8X69ATVxwL30SV6CGtb3eO9i+ayfpopts8PHm5/1YwlBJ/KrTvdRaRKha4WAeCGIrvlKWzcl5UCCw==",
- "requires": {
- "mnemonist": "0.38.3",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/fetch-http-handler": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.295.0.tgz",
- "integrity": "sha512-xs274LSLeF2313dAaq7gvm/m0e0tb0/Bt2vew4Lj2zP6YNRtuNlStfSNhYHHuIkOqjTwLeAmKdK+cWFnXKQPTA==",
- "requires": {
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/querystring-builder": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/util-base64": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/hash-node": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.295.0.tgz",
- "integrity": "sha512-jLq6QXUpvtYYu9+K8BECXpw7U52RBrewj/t/ALUVJsEhtwpx16K1WzMqwcVhkQ8mc/xQiki/T4eFSThODZAlcw==",
- "requires": {
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/util-buffer-from": "3.295.0",
- "@aws-sdk/util-utf8": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/invalid-dependency": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.295.0.tgz",
- "integrity": "sha512-ctXFKW4qnhLqZ0+qyEK1l0TOYQYwd2+vjj6wdjAiHuKoH6yIMqJ97LOT7oq3drvMQbnXa4I2jCOSFVuNSnzJ7Q==",
- "requires": {
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/is-array-buffer": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.295.0.tgz",
- "integrity": "sha512-SCIt10cr5dud7hvwveU4wkLjvkGssJ3GrcbHCds2NwI+JHmpcaaNYLAqi305JAuT29T36U5ssTFDSmrrEOcfag==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-content-length": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.295.0.tgz",
- "integrity": "sha512-XzrVPuO1JwxJx5PFHP9eMZLP9zyQxPZ8PM9gTWdOgoc1BMtxCkDZ3HLOnJtcfmfbz8nwSt2/H+wlBEXaRrf7Fg==",
- "requires": {
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-endpoint": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.295.0.tgz",
- "integrity": "sha512-MFRW6XyZABAOeFPu2CC37h+ol6ADaKs8fqqJrv9gtNb13r6c0UeztQFwI6V3tLlZwX7zzH7HcwYFKyks5VO6Xw==",
- "requires": {
- "@aws-sdk/middleware-serde": "3.295.0",
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/signature-v4": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/url-parser": "3.295.0",
- "@aws-sdk/util-config-provider": "3.295.0",
- "@aws-sdk/util-middleware": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-endpoint-discovery": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint-discovery/-/middleware-endpoint-discovery-3.295.0.tgz",
- "integrity": "sha512-wEezLBb/PFg2Nb+KHfJimFk+kRYE9a7G5vvs8zLXFelhunJ83TG0C+aSF4S3V5hMqngtZobV2mSJq4iwYEo6Ww==",
- "requires": {
- "@aws-sdk/config-resolver": "3.295.0",
- "@aws-sdk/endpoint-cache": "3.295.0",
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-host-header": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.295.0.tgz",
- "integrity": "sha512-CjdC8eCILSuNHTF2AZOtFta5lMvLMM3bXBTto0LKYeHQixgBHmRSgcShfBTiWEPgIgeNSFEjMbKX6bLnHSnODg==",
- "requires": {
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-logger": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.295.0.tgz",
- "integrity": "sha512-dbv0VTA7Dh6ZCkmCs0U7/ssZiDtHDI7Bq3zab+RxEyLEE4wr73bW6occq579U/QQJHOZQ6EBdvYig8ntRNlzVg==",
- "requires": {
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-recursion-detection": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.295.0.tgz",
- "integrity": "sha512-9Wjb8Y7H0ctL8gIKtGFwXhpHb3c2UGGi2P9I+p2PJwW08rDnMlOpUItY0v49SbZ+6uct1VNBs6iJ+jkv0h5MEQ==",
- "requires": {
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-retry": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.295.0.tgz",
- "integrity": "sha512-IdVX86VaDSSPcGI1JJM8lffabOMmGC9TUpskKkKdFnLW6eKtFohye+hlf2h6Y/2wdvoqCdi6XZyQX9WPJHiHtw==",
- "requires": {
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/service-error-classification": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/util-middleware": "3.295.0",
- "@aws-sdk/util-retry": "3.295.0",
- "tslib": "^2.5.0",
- "uuid": "^8.3.2"
- }
- },
- "@aws-sdk/middleware-sdk-ec2": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-ec2/-/middleware-sdk-ec2-3.295.0.tgz",
- "integrity": "sha512-XBWtECslU7WoV+CCvTPp0pzj4iBDfFYKeQNFKNp7q+t25uv2Gi+GH4a1DZ3tFAu36FRB0ZkVEk0l237rhgygtA==",
- "requires": {
- "@aws-sdk/middleware-endpoint": "3.295.0",
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/signature-v4": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/util-format-url": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-sdk-rds": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-rds/-/middleware-sdk-rds-3.310.0.tgz",
- "integrity": "sha512-V1nUsjggGLjy+Hx/z/7tb6bnfzZ1Kx4ikOdYVlTidnSCWZdh+kFE5Em16f5Q3erwG5Sil4Uxk0vpj+MSFP5MKA==",
- "requires": {
- "@aws-sdk/middleware-endpoint": "3.310.0",
- "@aws-sdk/protocol-http": "3.310.0",
- "@aws-sdk/signature-v4": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/util-format-url": "3.310.0",
- "tslib": "^2.5.0"
- },
- "dependencies": {
- "@aws-sdk/is-array-buffer": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.310.0.tgz",
- "integrity": "sha512-urnbcCR+h9NWUnmOtet/s4ghvzsidFmspfhYaHAmSRdy9yDjdjBJMFjjsn85A1ODUktztm+cVncXjQ38WCMjMQ==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-endpoint": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.310.0.tgz",
- "integrity": "sha512-Z+N2vOL8K354/lstkClxLLsr6hCpVRh+0tCMXrVj66/NtKysCEZ/0b9LmqOwD9pWHNiI2mJqXwY0gxNlKAroUg==",
- "requires": {
- "@aws-sdk/middleware-serde": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/url-parser": "3.310.0",
- "@aws-sdk/util-middleware": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-serde": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.310.0.tgz",
- "integrity": "sha512-RNeeTVWSLTaentUeCgQKZhAl+C6hxtwD78cQWS10UymWpQFwbaxztzKUu4UQS5xA2j6PxwPRRUjqa4jcFjfLsg==",
- "requires": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/protocol-http": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.310.0.tgz",
- "integrity": "sha512-fgZ1aw/irQtnrsR58pS8ThKOWo57Py3xX6giRvwSgZDEcxHfVzuQjy9yPuV++v04fdmdtgpbGf8WfvAAJ11yXQ==",
- "requires": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/querystring-builder": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.310.0.tgz",
- "integrity": "sha512-ZHH8GV/80+pWGo7DzsvwvXR5xVxUHXUvPJPFAkhr6nCf78igdoF8gR10ScFoEKbtEapoNTaZlKHPXxpD8aPG7A==",
- "requires": {
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/util-uri-escape": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/querystring-parser": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.310.0.tgz",
- "integrity": "sha512-YkIznoP6lsiIUHinx++/lbb3tlMURGGqMpo0Pnn32zYzGrJXA6eC3D0as2EcMjo55onTfuLcIiX4qzXes2MYOA==",
- "requires": {
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/signature-v4": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.310.0.tgz",
- "integrity": "sha512-1M60P1ZBNAjCFv9sYW29OF6okktaeibWyW3lMXqzoHF70lHBZh+838iUchznXUA5FLabfn4jBFWMRxlAXJUY2Q==",
- "requires": {
- "@aws-sdk/is-array-buffer": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "@aws-sdk/util-hex-encoding": "3.310.0",
- "@aws-sdk/util-middleware": "3.310.0",
- "@aws-sdk/util-uri-escape": "3.310.0",
- "@aws-sdk/util-utf8": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/types": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.310.0.tgz",
- "integrity": "sha512-j8eamQJ7YcIhw7fneUfs8LYl3t01k4uHi4ZDmNRgtbmbmTTG3FZc2MotStZnp3nZB6vLiPF1o5aoJxWVvkzS6A==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/url-parser": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.310.0.tgz",
- "integrity": "sha512-mCLnCaSB9rQvAgx33u0DujLvr4d5yEm/W5r789GblwwQnlNXedVu50QRizMLTpltYWyAUoXjJgQnJHmJMaKXhw==",
- "requires": {
- "@aws-sdk/querystring-parser": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-buffer-from": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.310.0.tgz",
- "integrity": "sha512-i6LVeXFtGih5Zs8enLrt+ExXY92QV25jtEnTKHsmlFqFAuL3VBeod6boeMXkN2p9lbSVVQ1sAOOYZOHYbYkntw==",
- "requires": {
- "@aws-sdk/is-array-buffer": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-format-url": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.310.0.tgz",
- "integrity": "sha512-NBOvmvvVR3ydquHmznfgtakiSgDhq8Ww6fq8TUaEjM+Es6+iqY4AwZo0rZ9xTX3GpCcoZy391HUi6kiXRAFzuA==",
- "requires": {
- "@aws-sdk/querystring-builder": "3.310.0",
- "@aws-sdk/types": "3.310.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-hex-encoding": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.310.0.tgz",
- "integrity": "sha512-sVN7mcCCDSJ67pI1ZMtk84SKGqyix6/0A1Ab163YKn+lFBQRMKexleZzpYzNGxYzmQS6VanP/cfU7NiLQOaSfA==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-middleware": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.310.0.tgz",
- "integrity": "sha512-FTSUKL/eRb9X6uEZClrTe27QFXUNNp7fxYrPndZwk1hlaOP5ix+MIHBcI7pIiiY/JPfOUmPyZOu+HetlFXjWog==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-uri-escape": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.310.0.tgz",
- "integrity": "sha512-drzt+aB2qo2LgtDoiy/3sVG8w63cgLkqFIa2NFlGpUgHFWTXkqtbgf4L5QdjRGKWhmZsnqkbtL7vkSWEcYDJ4Q==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-utf8": {
- "version": "3.310.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8/-/util-utf8-3.310.0.tgz",
- "integrity": "sha512-DnLfFT8uCO22uOJc0pt0DsSNau1GTisngBCDw8jQuWT5CqogMJu4b/uXmwEqfj8B3GX6Xsz8zOd6JpRlPftQoA==",
- "requires": {
- "@aws-sdk/util-buffer-from": "3.310.0",
- "tslib": "^2.5.0"
- }
- }
- }
- },
- "@aws-sdk/middleware-sdk-sts": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.295.0.tgz",
- "integrity": "sha512-QTHR+ZXAmii8XsbdRrqJWn6LVeGiRcFfGlniIb1YEjw1p2FU5kpayq8N1SLLtj3JWmE61Bpn0J+LAQmfjbCqFA==",
- "requires": {
- "@aws-sdk/middleware-signing": "3.295.0",
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/signature-v4": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-serde": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.295.0.tgz",
- "integrity": "sha512-LAKtKNKdu6Si7rmLatAq87LSa27mR6HUZ7tZHD2E4SQWOoNpS4ikKfUfATkbjC2GOfbrBYmFmQgBvpghYYZ3jw==",
- "requires": {
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-signing": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.295.0.tgz",
- "integrity": "sha512-LcNzGqtpo9sdWJ9mKtgjragncbin/Ynbz/pklH/HcIIi45w8ZVrhLBpW1iQZ0MBKyDacAAeWtXxKHy55DkHlvg==",
- "requires": {
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/signature-v4": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/util-middleware": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-stack": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.295.0.tgz",
- "integrity": "sha512-65HahosleRbpNgu6/XkABcrBmZHudRYTNpyKRfSY18QPKVQv3PRgRqv/goHrc6DHo8cxAliBoMciN88Ali1ufQ==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/middleware-user-agent": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.295.0.tgz",
- "integrity": "sha512-11MGXHFxmXgQx6aAFshLqHm3US7awXMP1Hq3IAu6j+GXSdkpkIojh/LlzRbSUftAhh23C5oQpgOkqs6fox4xCw==",
- "requires": {
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/util-endpoints": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/node-config-provider": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.295.0.tgz",
- "integrity": "sha512-6lkCmPMmXn6CF1qQHkE/Ii88ge/Mz9MWX+Krj3ICdBRwdMqm4LGzc9qG+bJeqbVI3tPO3djmL+b4SW4a3pvKsw==",
- "requires": {
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/shared-ini-file-loader": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/node-http-handler": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.295.0.tgz",
- "integrity": "sha512-Ga3vp/IY3LgzTdlSTAcxncYebE0lpQAdgxnko+z1i67OaI8DqNlTL8vdYBoHDaFOb9E6ErShLytVoHAEuJ5TpA==",
- "requires": {
- "@aws-sdk/abort-controller": "3.295.0",
- "@aws-sdk/protocol-http": "3.295.0",
- "@aws-sdk/querystring-builder": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/property-provider": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.295.0.tgz",
- "integrity": "sha512-5hxI1W36JWugYaBng7hKH2IxDtNohk0KMsz6wgyHVxTcsrO9VohlYa+5rHntmt3SbQAyy7n5ft9/vb1Nb5TGCw==",
- "requires": {
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/protocol-http": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.295.0.tgz",
- "integrity": "sha512-mDl1jfNDtOFXKQrkiTY0dbTwC9LLjmmAmE8TpxXC1v6JbOihVrARiyPdumZWP4J/71YAim1ASS6JlQHw/GuAqg==",
- "requires": {
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/querystring-builder": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.295.0.tgz",
- "integrity": "sha512-zgFb2pSkxOCHVusZpPjQVIwmQZf59MQEYJETk42OKaigItGTHjap9DrFzKo6+SrHeyEpJLxlZKSz5up4Hulwdw==",
- "requires": {
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/util-uri-escape": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/querystring-parser": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.295.0.tgz",
- "integrity": "sha512-bcm8IBHmflH1e6EHznScJbfvAmNZqwZtC6QaynNk6no/YYKr5Swm+GHqxurKBm86qCYIOoSvdoq8tyhUjXnh4Q==",
- "requires": {
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/service-error-classification": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.295.0.tgz",
- "integrity": "sha512-zqGxXkZUxPD7E0FJXKHZLuJwr02zg/Ux4d+elT/MUTYT9eKupmG2S5586/hZdjUxGGA7gmMMJr92mjrLVJUAkQ=="
- },
- "@aws-sdk/shared-ini-file-loader": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.295.0.tgz",
- "integrity": "sha512-LF9+jk37/VPoIyadeb+Ls0Tqda6dauo3uG7FDfg7qdiOpdyNRuFaIZE//MTSG5mk4ExAwjkFsnslZaw31hbbUw==",
- "requires": {
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/signature-v4": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.295.0.tgz",
- "integrity": "sha512-yS00sIwWEnPB4aHZWJZpXVL2/wbwrymxbPZw/Xq0JXbR9+RXhzENBqw7C3d7E11K1xLnoTYlVqcJhNuNXgyeZg==",
- "requires": {
- "@aws-sdk/is-array-buffer": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "@aws-sdk/util-hex-encoding": "3.295.0",
- "@aws-sdk/util-middleware": "3.295.0",
- "@aws-sdk/util-uri-escape": "3.295.0",
- "@aws-sdk/util-utf8": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/smithy-client": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.295.0.tgz",
- "integrity": "sha512-6Ifq+szMeX6MjWkEEiXvQGm7moY5Wt6WfFi+dMLkZmPdOEWYB0Cr0EBpY605WHWGz702CpFLvM/z6rUkvtak5g==",
- "requires": {
- "@aws-sdk/middleware-stack": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/token-providers": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.295.0.tgz",
- "integrity": "sha512-/6PsplDacgBoQxFBbKYMW9ZlEeTHHdAm+xE6V+qjEsc0YXy32LwuFllfihryXLjWftrC3kr8EiehLU6d+9JaKA==",
- "requires": {
- "@aws-sdk/client-sso-oidc": "3.295.0",
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/shared-ini-file-loader": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/types": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.295.0.tgz",
- "integrity": "sha512-flwibucy5+PshdFLeMCClMqV3eFmjUDhcLkEUeQvVgyhGxJPIrU3ntGAfqz27bvk47ZVX5TUdCG5JdxuUaRO+A==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/url-parser": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.295.0.tgz",
- "integrity": "sha512-hev5gbi+EWHLaFNgVpoNeNTaJpqfa9ev0SvqgvCPqGlIdUnt3cP9t1Mc8jvx2kUk8ebPtrrq6cp8ZslfxoFeVA==",
- "requires": {
- "@aws-sdk/querystring-parser": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-base64": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64/-/util-base64-3.295.0.tgz",
- "integrity": "sha512-z1r40BsBiOTALnzASvLb4qutGwPpL+jH2UKTCV5WJLXZFMzRnpZaRfeZGE8lMJ/i0+jv9H9G1FmVzE8UgB4rhw==",
- "requires": {
- "@aws-sdk/util-buffer-from": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-body-length-browser": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.295.0.tgz",
- "integrity": "sha512-NbG4/RSHV1VueStPRclSo5zRjNUmcDlNAs29sniZF+YaN0+Ad7hEdu/YgJw39shBfUaurz2Wv0pufU3cxE5Tng==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-body-length-node": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-node/-/util-body-length-node-3.295.0.tgz",
- "integrity": "sha512-dvGf8VBmrT66lM0n6P/h7wnlHS4Atafyivyl8f4TUCMvRdpqryvvrtnX6yYcq3T7VKQmas/2SOlgDvcrhGXaiw==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-buffer-from": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.295.0.tgz",
- "integrity": "sha512-5ezVEITQnrQKn+CU9qfZHgRp2nrrbX0Clmlm9aiNjAEQEPHY33tWl0t6n8h8yU+IpGiNRMWBVC4aSJaE5NA1mA==",
- "requires": {
- "@aws-sdk/is-array-buffer": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-config-provider": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-config-provider/-/util-config-provider-3.295.0.tgz",
- "integrity": "sha512-/5Dl1aV2yI8YQjqwmg4RTnl/E9NmNsx7HIwBZt+dTcOrM0LMUwczQBFFcLyqCj/qv5y+VsvLoAAA/OiBT7hb3w==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-defaults-mode-browser": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.295.0.tgz",
- "integrity": "sha512-QqVyl4Sxi9Umn2+TdhZR8fHQRWWs2361JCylig1GzH+ud+8jinDS6tLtWxhzrea2XdKGb4xqjTC4AhCuBqgSmA==",
- "requires": {
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "bowser": "^2.11.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-defaults-mode-node": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.295.0.tgz",
- "integrity": "sha512-R1e94v6HMsUec8/P2tJmab5fYsT9X3+Kh1rMzCEA27V+kAD88eKStzE26Yb1kQDAC+Fg3Fe1KS1bg4dmQKUSVg==",
- "requires": {
- "@aws-sdk/config-resolver": "3.295.0",
- "@aws-sdk/credential-provider-imds": "3.295.0",
- "@aws-sdk/node-config-provider": "3.295.0",
- "@aws-sdk/property-provider": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-endpoints": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.295.0.tgz",
- "integrity": "sha512-WZR6jAD++7Wb6ER1SM/U82xU+OVWihcc8V90AzTWyDb0JPeKuogwWokV1aHXiGaQGbWULr1wY1R3wthhvEs3Bg==",
- "requires": {
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-format-url": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.295.0.tgz",
- "integrity": "sha512-sONC9XCz6jtib1Ydh1EfEfKZR2/KZVdHv/KUx8VosPzMEnh6+maqfrdeHN6qQZJNdK/na2ZOIhONMDVCRktT9w==",
- "requires": {
- "@aws-sdk/querystring-builder": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-hex-encoding": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.295.0.tgz",
- "integrity": "sha512-XJcoVo41kHzhe28PBm/rqt5mdCp8R6abwiW9ug1dA6FOoPUO8kBUxDv6xaOmA2hfRvd2ocFfBXaUCBqUowkGcQ==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-locate-window": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.295.0.tgz",
- "integrity": "sha512-d/s+zhUx5Kh4l/ecMP/TBjzp1GR/g89Q4nWH6+wH5WgdHsK+LG+vmsk6mVNuP/8wsCofYG4NBqp5Ulbztbm9QA==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-middleware": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.295.0.tgz",
- "integrity": "sha512-t6UdduLHV97IRZmd1YA0v5HCwerz+OXxDF8lLK0G7qihde0jv6tq5w8fTTjgehDFKM0UGUiaahOtjEcRK7F2Aw==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-retry": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-retry/-/util-retry-3.295.0.tgz",
- "integrity": "sha512-3xp3A5XtPWGsN9aLuzM3mB4hpM3nZJ5JJiGFgUXu/CTP2ahipbVbMwtRpIUjYDh1kvdjoaDJatEVJ7JhJrXFew==",
- "requires": {
- "@aws-sdk/service-error-classification": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-uri-escape": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.295.0.tgz",
- "integrity": "sha512-1H5DcyIoXF8XcPBWf7wzHt0l+TW2EoR8Oq4gsVrPTQkHMTVclC2Yn8EF3gc4arwVBzwLulI9LMBE2L8fexGfTQ==",
- "requires": {
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-user-agent-browser": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.295.0.tgz",
- "integrity": "sha512-lSU80r6yMwSDLkBZ0900G/kHLz/QgXewPXz56Xnq7NHWu7YliY6fzT1zWHPRGwcfCctTGMTWw+10ZSu/0Xv9nw==",
- "requires": {
- "@aws-sdk/types": "3.295.0",
- "bowser": "^2.11.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-user-agent-node": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.295.0.tgz",
- "integrity": "sha512-EVt/4nWTYLbS6llhjE4sn2tn1mBlifyK6ezAse5kr6boNG3dJt6Y7gHAXXglkmblw2bflxqgOaKj5YCcZFUSyQ==",
- "requires": {
- "@aws-sdk/node-config-provider": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-utf8": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8/-/util-utf8-3.295.0.tgz",
- "integrity": "sha512-ITN8v3F63ZkA4sdmCtSbS/mhav4F0MEAiXDAUXtMJLNqVtaVcyQST4i9vNmPpIVthAPAtP0QjyF2tq/Di8bxtQ==",
- "requires": {
- "@aws-sdk/util-buffer-from": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-sdk/util-utf8-browser": {
- "version": "3.259.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz",
- "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==",
- "requires": {
- "tslib": "^2.3.1"
- }
- },
- "@aws-sdk/util-waiter": {
- "version": "3.295.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-waiter/-/util-waiter-3.295.0.tgz",
- "integrity": "sha512-7FHJhSqfBSGsbNUtXyJvu0cnKCtVoQ1HtVZ2OWvW9V0Vyi++ifm6UFvHecrQPocfXu4WoOEhWktZ78iUdCA/MA==",
- "requires": {
- "@aws-sdk/abort-controller": "3.295.0",
- "@aws-sdk/types": "3.295.0",
- "tslib": "^2.5.0"
- }
- },
- "@aws-solutions-constructs/aws-lambda-dynamodb": {
- "version": "2.30.0",
- "resolved": "https://registry.npmjs.org/@aws-solutions-constructs/aws-lambda-dynamodb/-/aws-lambda-dynamodb-2.30.0.tgz",
- "integrity": "sha512-Agh1RNZI3qhIJuPOdCMzv8RzBZZH8NdfMsYkiVvn4hEB/h4/arFfeArxL5z8SlJbvFwK2Dg08L2UXdtJSlH6AA==",
- "requires": {
- "@aws-solutions-constructs/core": "2.30.0"
- }
- },
- "@aws-solutions-constructs/core": {
- "version": "2.30.0",
- "resolved": "https://registry.npmjs.org/@aws-solutions-constructs/core/-/core-2.30.0.tgz",
- "integrity": "sha512-0sSifWV7QnQIuVlXK5LXDqYt/U7tWNHOpNsfWTivQ6fmPojhjprLmFkgIa/G3+CxWXDSaWUgUFzyhLcT72xt0Q==",
- "requires": {
- "deep-diff": "^1.0.2",
- "deepmerge": "^4.0.0",
- "npmlog": "^4.1.2"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "2.1.1",
- "bundled": true
- },
- "aproba": {
- "version": "1.2.0",
- "bundled": true
- },
- "are-we-there-yet": {
- "version": "1.1.7",
- "bundled": true,
- "requires": {
- "delegates": "^1.0.0",
- "readable-stream": "^2.0.6"
- }
- },
- "code-point-at": {
- "version": "1.1.0",
- "bundled": true
- },
- "console-control-strings": {
- "version": "1.1.0",
- "bundled": true
- },
- "core-util-is": {
- "version": "1.0.3",
- "bundled": true
- },
- "deep-diff": {
- "version": "1.0.2",
- "bundled": true
- },
- "deepmerge": {
- "version": "4.2.2",
- "bundled": true
- },
- "delegates": {
- "version": "1.0.0",
- "bundled": true
- },
- "emoji-regex": {
- "version": "8.0.0",
- "bundled": true
- },
- "gauge": {
- "version": "2.7.4",
- "bundled": true,
- "requires": {
- "aproba": "^1.0.3",
- "console-control-strings": "^1.0.0",
- "has-unicode": "^2.0.0",
- "object-assign": "^4.1.0",
- "signal-exit": "^3.0.0",
- "string-width": "^1.0.1",
- "strip-ansi": "^3.0.1",
- "wide-align": "^1.1.0"
- }
- },
- "has-unicode": {
- "version": "2.0.1",
- "bundled": true
- },
- "inherits": {
- "version": "2.0.4",
- "bundled": true
- },
- "is-fullwidth-code-point": {
- "version": "1.0.0",
- "bundled": true,
- "requires": {
- "number-is-nan": "^1.0.0"
- }
- },
- "isarray": {
- "version": "1.0.0",
- "bundled": true
- },
- "npmlog": {
- "version": "4.1.2",
- "bundled": true,
- "requires": {
- "are-we-there-yet": "~1.1.2",
- "console-control-strings": "~1.1.0",
- "gauge": "~2.7.3",
- "set-blocking": "~2.0.0"
- }
- },
- "number-is-nan": {
- "version": "1.0.1",
- "bundled": true
- },
- "object-assign": {
- "version": "4.1.1",
- "bundled": true
- },
- "process-nextick-args": {
- "version": "2.0.1",
- "bundled": true
- },
- "readable-stream": {
- "version": "2.3.7",
- "bundled": true,
- "requires": {
- "core-util-is": "~1.0.0",
- "inherits": "~2.0.3",
- "isarray": "~1.0.0",
- "process-nextick-args": "~2.0.0",
- "safe-buffer": "~5.1.1",
- "string_decoder": "~1.1.1",
- "util-deprecate": "~1.0.1"
- }
- },
- "safe-buffer": {
- "version": "5.1.2",
- "bundled": true
- },
- "set-blocking": {
- "version": "2.0.0",
- "bundled": true
- },
- "signal-exit": {
- "version": "3.0.7",
- "bundled": true
- },
- "string_decoder": {
- "version": "1.1.1",
- "bundled": true,
- "requires": {
- "safe-buffer": "~5.1.0"
- }
- },
- "string-width": {
- "version": "1.0.2",
- "bundled": true,
- "requires": {
- "code-point-at": "^1.0.0",
- "is-fullwidth-code-point": "^1.0.0",
- "strip-ansi": "^3.0.0"
- }
- },
- "strip-ansi": {
- "version": "3.0.1",
- "bundled": true,
- "requires": {
- "ansi-regex": "^2.0.0"
- }
- },
- "util-deprecate": {
- "version": "1.0.2",
- "bundled": true
- },
- "wide-align": {
- "version": "1.1.5",
- "bundled": true,
- "requires": {
- "string-width": "^1.0.2 || 2 || 3 || 4"
- },
- "dependencies": {
- "ansi-regex": {
- "version": "5.0.1",
- "bundled": true
- },
- "is-fullwidth-code-point": {
- "version": "3.0.0",
- "bundled": true
- },
- "string-width": {
- "version": "4.2.3",
- "bundled": true,
- "requires": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- }
- },
- "strip-ansi": {
- "version": "6.0.1",
- "bundled": true,
- "requires": {
- "ansi-regex": "^5.0.1"
- }
- }
- }
- }
- }
- },
- "@babel/code-frame": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
- "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==",
- "dev": true,
- "requires": {
- "@babel/highlight": "^7.18.6"
- }
- },
- "@babel/compat-data": {
- "version": "7.20.10",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.10.tgz",
- "integrity": "sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg==",
- "dev": true
- },
- "@babel/core": {
- "version": "7.20.12",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz",
- "integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==",
- "dev": true,
- "requires": {
- "@ampproject/remapping": "^2.1.0",
- "@babel/code-frame": "^7.18.6",
- "@babel/generator": "^7.20.7",
- "@babel/helper-compilation-targets": "^7.20.7",
- "@babel/helper-module-transforms": "^7.20.11",
- "@babel/helpers": "^7.20.7",
- "@babel/parser": "^7.20.7",
- "@babel/template": "^7.20.7",
- "@babel/traverse": "^7.20.12",
- "@babel/types": "^7.20.7",
- "convert-source-map": "^1.7.0",
- "debug": "^4.1.0",
- "gensync": "^1.0.0-beta.2",
- "json5": "^2.2.2",
- "semver": "^6.3.0"
- },
- "dependencies": {
- "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
- }
- }
- },
- "@babel/generator": {
- "version": "7.20.7",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.7.tgz",
- "integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.20.7",
- "@jridgewell/gen-mapping": "^0.3.2",
- "jsesc": "^2.5.1"
- },
- "dependencies": {
- "@jridgewell/gen-mapping": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
- "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
- "dev": true,
- "requires": {
- "@jridgewell/set-array": "^1.0.1",
- "@jridgewell/sourcemap-codec": "^1.4.10",
- "@jridgewell/trace-mapping": "^0.3.9"
- }
- }
- }
- },
- "@babel/helper-compilation-targets": {
- "version": "7.20.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz",
- "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==",
- "dev": true,
- "requires": {
- "@babel/compat-data": "^7.20.5",
- "@babel/helper-validator-option": "^7.18.6",
- "browserslist": "^4.21.3",
- "lru-cache": "^5.1.1",
- "semver": "^6.3.0"
- }
- },
- "@babel/helper-environment-visitor": {
- "version": "7.18.9",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz",
- "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==",
- "dev": true
- },
- "@babel/helper-function-name": {
- "version": "7.19.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz",
- "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==",
- "dev": true,
- "requires": {
- "@babel/template": "^7.18.10",
- "@babel/types": "^7.19.0"
- }
- },
- "@babel/helper-hoist-variables": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz",
- "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.18.6"
- }
- },
- "@babel/helper-module-imports": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz",
- "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.18.6"
- }
- },
- "@babel/helper-module-transforms": {
- "version": "7.20.11",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz",
- "integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==",
- "dev": true,
- "requires": {
- "@babel/helper-environment-visitor": "^7.18.9",
- "@babel/helper-module-imports": "^7.18.6",
- "@babel/helper-simple-access": "^7.20.2",
- "@babel/helper-split-export-declaration": "^7.18.6",
- "@babel/helper-validator-identifier": "^7.19.1",
- "@babel/template": "^7.20.7",
- "@babel/traverse": "^7.20.10",
- "@babel/types": "^7.20.7"
- }
- },
- "@babel/helper-plugin-utils": {
- "version": "7.20.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz",
- "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==",
- "dev": true
- },
- "@babel/helper-simple-access": {
- "version": "7.20.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz",
- "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.20.2"
- }
- },
- "@babel/helper-split-export-declaration": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz",
- "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.18.6"
- }
- },
- "@babel/helper-string-parser": {
- "version": "7.19.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz",
- "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==",
- "dev": true
- },
- "@babel/helper-validator-identifier": {
- "version": "7.19.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
- "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
- "dev": true
- },
- "@babel/helper-validator-option": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz",
- "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==",
- "dev": true
- },
- "@babel/helpers": {
- "version": "7.20.7",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.7.tgz",
- "integrity": "sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA==",
- "dev": true,
- "requires": {
- "@babel/template": "^7.20.7",
- "@babel/traverse": "^7.20.7",
- "@babel/types": "^7.20.7"
- }
- },
- "@babel/highlight": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
- "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
- "dev": true,
- "requires": {
- "@babel/helper-validator-identifier": "^7.18.6",
- "chalk": "^2.0.0",
- "js-tokens": "^4.0.0"
- },
- "dependencies": {
- "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,
- "requires": {
- "color-convert": "^1.9.0"
- }
- },
- "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,
- "requires": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- }
- },
- "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,
- "requires": {
- "color-name": "1.1.3"
- }
- },
- "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
- },
- "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
- },
- "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
- },
- "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,
- "requires": {
- "has-flag": "^3.0.0"
- }
- }
- }
- },
- "@babel/parser": {
- "version": "7.20.7",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz",
- "integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==",
- "dev": true
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.12.13"
- }
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@babel/plugin-syntax-jsx": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz",
- "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.18.6"
- }
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.10.4"
- }
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.8.0"
- }
- },
- "@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,
- "requires": {
- "@babel/helper-plugin-utils": "^7.14.5"
- }
- },
- "@babel/plugin-syntax-typescript": {
- "version": "7.20.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz",
- "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==",
- "dev": true,
- "requires": {
- "@babel/helper-plugin-utils": "^7.19.0"
- }
- },
- "@babel/template": {
- "version": "7.20.7",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz",
- "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.18.6",
- "@babel/parser": "^7.20.7",
- "@babel/types": "^7.20.7"
- }
- },
- "@babel/traverse": {
- "version": "7.20.12",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.12.tgz",
- "integrity": "sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ==",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.18.6",
- "@babel/generator": "^7.20.7",
- "@babel/helper-environment-visitor": "^7.18.9",
- "@babel/helper-function-name": "^7.19.0",
- "@babel/helper-hoist-variables": "^7.18.6",
- "@babel/helper-split-export-declaration": "^7.18.6",
- "@babel/parser": "^7.20.7",
- "@babel/types": "^7.20.7",
- "debug": "^4.1.0",
- "globals": "^11.1.0"
- }
- },
- "@babel/types": {
- "version": "7.20.7",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz",
- "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==",
- "dev": true,
- "requires": {
- "@babel/helper-string-parser": "^7.19.4",
- "@babel/helper-validator-identifier": "^7.19.1",
- "to-fast-properties": "^2.0.0"
- }
- },
- "@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
- },
- "@cspotcode/source-map-support": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
- "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
- "dev": true,
- "requires": {
- "@jridgewell/trace-mapping": "0.3.9"
- },
- "dependencies": {
- "@jridgewell/trace-mapping": {
- "version": "0.3.9",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
- "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
- "dev": true,
- "requires": {
- "@jridgewell/resolve-uri": "^3.0.3",
- "@jridgewell/sourcemap-codec": "^1.4.10"
- }
- }
- }
- },
- "@eslint-community/eslint-utils": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
- "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
- "dev": true,
- "requires": {
- "eslint-visitor-keys": "^3.3.0"
- }
- },
- "@eslint-community/regexpp": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.1.tgz",
- "integrity": "sha512-BISJ6ZE4xQsuL/FmsyRaiffpq977bMlsKfGHTQrOGFErfByxIe6iZTxPf/00Zon9b9a7iUykfQwejN3s2ZW/Bw==",
- "dev": true
- },
- "@eslint/eslintrc": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz",
- "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==",
- "dev": true,
- "requires": {
- "ajv": "^6.12.4",
- "debug": "^4.3.2",
- "espree": "^9.5.0",
- "globals": "^13.19.0",
- "ignore": "^5.2.0",
- "import-fresh": "^3.2.1",
- "js-yaml": "^4.1.0",
- "minimatch": "^3.1.2",
- "strip-json-comments": "^3.1.1"
- },
- "dependencies": {
- "argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true
- },
- "globals": {
- "version": "13.20.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
- "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
- "dev": true,
- "requires": {
- "type-fest": "^0.20.2"
- }
- },
- "js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
- "dev": true,
- "requires": {
- "argparse": "^2.0.1"
- }
- },
- "type-fest": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
- "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
- "dev": true
- }
- }
- },
- "@eslint/js": {
- "version": "8.36.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz",
- "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==",
- "dev": true
- },
- "@humanwhocodes/config-array": {
- "version": "0.11.8",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
- "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==",
- "dev": true,
- "requires": {
- "@humanwhocodes/object-schema": "^1.2.1",
- "debug": "^4.1.1",
- "minimatch": "^3.0.5"
- }
- },
- "@humanwhocodes/module-importer": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
- "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
- "dev": true
- },
- "@humanwhocodes/object-schema": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
- "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
- "dev": true
- },
- "@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,
- "requires": {
- "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"
- }
- },
- "@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
- },
- "@jest/console": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.3.1.tgz",
- "integrity": "sha512-IRE6GD47KwcqA09RIWrabKdHPiKDGgtAL31xDxbi/RjQMsr+lY+ppxmHwY0dUEV3qvvxZzoe5Hl0RXZJOjQNUg==",
- "dev": true,
- "requires": {
- "@jest/types": "^29.3.1",
- "@types/node": "*",
- "chalk": "^4.0.0",
- "jest-message-util": "^29.3.1",
- "jest-util": "^29.3.1",
- "slash": "^3.0.0"
- }
- },
- "@jest/core": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.3.1.tgz",
- "integrity": "sha512-0ohVjjRex985w5MmO5L3u5GR1O30DexhBSpuwx2P+9ftyqHdJXnk7IUWiP80oHMvt7ubHCJHxV0a0vlKVuZirw==",
- "dev": true,
- "requires": {
- "@jest/console": "^29.3.1",
- "@jest/reporters": "^29.3.1",
- "@jest/test-result": "^29.3.1",
- "@jest/transform": "^29.3.1",
- "@jest/types": "^29.3.1",
- "@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.2.0",
- "jest-config": "^29.3.1",
- "jest-haste-map": "^29.3.1",
- "jest-message-util": "^29.3.1",
- "jest-regex-util": "^29.2.0",
- "jest-resolve": "^29.3.1",
- "jest-resolve-dependencies": "^29.3.1",
- "jest-runner": "^29.3.1",
- "jest-runtime": "^29.3.1",
- "jest-snapshot": "^29.3.1",
- "jest-util": "^29.3.1",
- "jest-validate": "^29.3.1",
- "jest-watcher": "^29.3.1",
- "micromatch": "^4.0.4",
- "pretty-format": "^29.3.1",
- "slash": "^3.0.0",
- "strip-ansi": "^6.0.0"
- },
- "dependencies": {
- "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
- },
- "pretty-format": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz",
- "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==",
- "dev": true,
- "requires": {
- "@jest/schemas": "^29.0.0",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- }
- },
- "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
- }
- }
- },
- "@jest/environment": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.3.1.tgz",
- "integrity": "sha512-pMmvfOPmoa1c1QpfFW0nXYtNLpofqo4BrCIk6f2kW4JFeNlHV2t3vd+3iDLf31e2ot2Mec0uqZfmI+U0K2CFag==",
- "dev": true,
- "requires": {
- "@jest/fake-timers": "^29.3.1",
- "@jest/types": "^29.3.1",
- "@types/node": "*",
- "jest-mock": "^29.3.1"
- }
- },
- "@jest/expect": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.3.1.tgz",
- "integrity": "sha512-QivM7GlSHSsIAWzgfyP8dgeExPRZ9BIe2LsdPyEhCGkZkoyA+kGsoIzbKAfZCvvRzfZioKwPtCZIt5SaoxYCvg==",
- "dev": true,
- "requires": {
- "expect": "^29.3.1",
- "jest-snapshot": "^29.3.1"
- }
- },
- "@jest/expect-utils": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.3.1.tgz",
- "integrity": "sha512-wlrznINZI5sMjwvUoLVk617ll/UYfGIZNxmbU+Pa7wmkL4vYzhV9R2pwVqUh4NWWuLQWkI8+8mOkxs//prKQ3g==",
- "dev": true,
- "requires": {
- "jest-get-type": "^29.2.0"
- }
- },
- "@jest/fake-timers": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.3.1.tgz",
- "integrity": "sha512-iHTL/XpnDlFki9Tq0Q1GGuVeQ8BHZGIYsvCO5eN/O/oJaRzofG9Xndd9HuSDBI/0ZS79pg0iwn07OMTQ7ngF2A==",
- "dev": true,
- "requires": {
- "@jest/types": "^29.3.1",
- "@sinonjs/fake-timers": "^9.1.2",
- "@types/node": "*",
- "jest-message-util": "^29.3.1",
- "jest-mock": "^29.3.1",
- "jest-util": "^29.3.1"
- }
- },
- "@jest/globals": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.3.1.tgz",
- "integrity": "sha512-cTicd134vOcwO59OPaB6AmdHQMCtWOe+/DitpTZVxWgMJ+YvXL1HNAmPyiGbSHmF/mXVBkvlm8YYtQhyHPnV6Q==",
- "dev": true,
- "requires": {
- "@jest/environment": "^29.3.1",
- "@jest/expect": "^29.3.1",
- "@jest/types": "^29.3.1",
- "jest-mock": "^29.3.1"
- }
- },
- "@jest/reporters": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.3.1.tgz",
- "integrity": "sha512-GhBu3YFuDrcAYW/UESz1JphEAbvUjaY2vShRZRoRY1mxpCMB3yGSJ4j9n0GxVlEOdCf7qjvUfBCrTUUqhVfbRA==",
- "dev": true,
- "requires": {
- "@bcoe/v8-coverage": "^0.2.3",
- "@jest/console": "^29.3.1",
- "@jest/test-result": "^29.3.1",
- "@jest/transform": "^29.3.1",
- "@jest/types": "^29.3.1",
- "@jridgewell/trace-mapping": "^0.3.15",
- "@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": "^5.1.0",
- "istanbul-lib-report": "^3.0.0",
- "istanbul-lib-source-maps": "^4.0.0",
- "istanbul-reports": "^3.1.3",
- "jest-message-util": "^29.3.1",
- "jest-util": "^29.3.1",
- "jest-worker": "^29.3.1",
- "slash": "^3.0.0",
- "string-length": "^4.0.1",
- "strip-ansi": "^6.0.0",
- "v8-to-istanbul": "^9.0.1"
- }
- },
- "@jest/schemas": {
- "version": "29.4.3",
- "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz",
- "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==",
- "dev": true,
- "requires": {
- "@sinclair/typebox": "^0.25.16"
- }
- },
- "@jest/source-map": {
- "version": "29.2.0",
- "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.2.0.tgz",
- "integrity": "sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ==",
- "dev": true,
- "requires": {
- "@jridgewell/trace-mapping": "^0.3.15",
- "callsites": "^3.0.0",
- "graceful-fs": "^4.2.9"
- }
- },
- "@jest/test-result": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.3.1.tgz",
- "integrity": "sha512-qeLa6qc0ddB0kuOZyZIhfN5q0e2htngokyTWsGriedsDhItisW7SDYZ7ceOe57Ii03sL988/03wAcBh3TChMGw==",
- "dev": true,
- "requires": {
- "@jest/console": "^29.3.1",
- "@jest/types": "^29.3.1",
- "@types/istanbul-lib-coverage": "^2.0.0",
- "collect-v8-coverage": "^1.0.0"
- }
- },
- "@jest/test-sequencer": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.3.1.tgz",
- "integrity": "sha512-IqYvLbieTv20ArgKoAMyhLHNrVHJfzO6ARZAbQRlY4UGWfdDnLlZEF0BvKOMd77uIiIjSZRwq3Jb3Fa3I8+2UA==",
- "dev": true,
- "requires": {
- "@jest/test-result": "^29.3.1",
- "graceful-fs": "^4.2.9",
- "jest-haste-map": "^29.3.1",
- "slash": "^3.0.0"
- }
- },
- "@jest/transform": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.3.1.tgz",
- "integrity": "sha512-8wmCFBTVGYqFNLWfcOWoVuMuKYPUBTnTMDkdvFtAYELwDOl9RGwOsvQWGPFxDJ8AWY9xM/8xCXdqmPK3+Q5Lug==",
- "dev": true,
- "requires": {
- "@babel/core": "^7.11.6",
- "@jest/types": "^29.3.1",
- "@jridgewell/trace-mapping": "^0.3.15",
- "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.3.1",
- "jest-regex-util": "^29.2.0",
- "jest-util": "^29.3.1",
- "micromatch": "^4.0.4",
- "pirates": "^4.0.4",
- "slash": "^3.0.0",
- "write-file-atomic": "^4.0.1"
- }
- },
- "@jest/types": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.3.1.tgz",
- "integrity": "sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA==",
- "dev": true,
- "requires": {
- "@jest/schemas": "^29.0.0",
- "@types/istanbul-lib-coverage": "^2.0.0",
- "@types/istanbul-reports": "^3.0.0",
- "@types/node": "*",
- "@types/yargs": "^17.0.8",
- "chalk": "^4.0.0"
- }
- },
- "@jridgewell/gen-mapping": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
- "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==",
- "dev": true,
- "requires": {
- "@jridgewell/set-array": "^1.0.0",
- "@jridgewell/sourcemap-codec": "^1.4.10"
- }
- },
- "@jridgewell/resolve-uri": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
- "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
- "dev": true
- },
- "@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
- },
- "@jridgewell/sourcemap-codec": {
- "version": "1.4.14",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
- "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
- "dev": true
- },
- "@jridgewell/trace-mapping": {
- "version": "0.3.17",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz",
- "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==",
- "dev": true,
- "requires": {
- "@jridgewell/resolve-uri": "3.1.0",
- "@jridgewell/sourcemap-codec": "1.4.14"
- }
- },
- "@nodelib/fs.scandir": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
- "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
- "dev": true,
- "requires": {
- "@nodelib/fs.stat": "2.0.5",
- "run-parallel": "^1.1.9"
- }
- },
- "@nodelib/fs.stat": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
- "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
- "dev": true
- },
- "@nodelib/fs.walk": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
- "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
- "dev": true,
- "requires": {
- "@nodelib/fs.scandir": "2.1.5",
- "fastq": "^1.6.0"
- }
- },
- "@sinclair/typebox": {
- "version": "0.25.24",
- "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz",
- "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==",
- "dev": true
- },
- "@sinonjs/commons": {
- "version": "1.8.6",
- "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz",
- "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==",
- "dev": true,
- "requires": {
- "type-detect": "4.0.8"
- }
- },
- "@sinonjs/fake-timers": {
- "version": "9.1.2",
- "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.2.tgz",
- "integrity": "sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==",
- "dev": true,
- "requires": {
- "@sinonjs/commons": "^1.7.0"
- }
- },
- "@tsconfig/node10": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
- "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==",
- "dev": true
- },
- "@tsconfig/node12": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
- "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
- "dev": true
- },
- "@tsconfig/node14": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
- "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
- "dev": true
- },
- "@tsconfig/node16": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz",
- "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==",
- "dev": true
- },
- "@types/babel__core": {
- "version": "7.1.20",
- "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.20.tgz",
- "integrity": "sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ==",
- "dev": true,
- "requires": {
- "@babel/parser": "^7.1.0",
- "@babel/types": "^7.0.0",
- "@types/babel__generator": "*",
- "@types/babel__template": "*",
- "@types/babel__traverse": "*"
- }
- },
- "@types/babel__generator": {
- "version": "7.6.4",
- "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz",
- "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.0.0"
- }
- },
- "@types/babel__template": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz",
- "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==",
- "dev": true,
- "requires": {
- "@babel/parser": "^7.1.0",
- "@babel/types": "^7.0.0"
- }
- },
- "@types/babel__traverse": {
- "version": "7.18.3",
- "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz",
- "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==",
- "dev": true,
- "requires": {
- "@babel/types": "^7.3.0"
- }
- },
- "@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,
- "requires": {
- "@types/node": "*"
- }
- },
- "@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
- },
- "@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,
- "requires": {
- "@types/istanbul-lib-coverage": "*"
- }
- },
- "@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,
- "requires": {
- "@types/istanbul-lib-report": "*"
- }
- },
- "@types/jest": {
- "version": "26.0.24",
- "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.24.tgz",
- "integrity": "sha512-E/X5Vib8BWqZNRlDxj9vYXhsDwPYbPINqKF9BsnSoon4RQ0D9moEuLD8txgyypFLH7J4+Lho9Nr/c8H0Fi+17w==",
- "dev": true,
- "requires": {
- "jest-diff": "^26.0.0",
- "pretty-format": "^26.0.0"
- }
- },
- "@types/json-schema": {
- "version": "7.0.11",
- "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
- "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
- "dev": true
- },
- "@types/json5": {
- "version": "0.0.29",
- "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
- "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
- "dev": true
- },
- "@types/node": {
- "version": "10.17.27",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.27.tgz",
- "integrity": "sha512-J0oqm9ZfAXaPdwNXMMgAhylw5fhmXkToJd06vuDUSAgEDZ/n/69/69UmyBZbc+zT34UnShuDSBqvim3SPnozJg==",
- "dev": true
- },
- "@types/prettier": {
- "version": "2.7.2",
- "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz",
- "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==",
- "dev": true
- },
- "@types/semver": {
- "version": "7.3.13",
- "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz",
- "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==",
- "dev": true
- },
- "@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
- },
- "@types/yargs": {
- "version": "17.0.19",
- "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.19.tgz",
- "integrity": "sha512-cAx3qamwaYX9R0fzOIZAlFpo4A+1uBVCxqpKz9D26uTF4srRXaGTTsikQmaotCtNdbhzyUH7ft6p9ktz9s6UNQ==",
- "dev": true,
- "requires": {
- "@types/yargs-parser": "*"
- }
- },
- "@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
- },
- "@typescript-eslint/eslint-plugin": {
- "version": "5.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.56.0.tgz",
- "integrity": "sha512-ZNW37Ccl3oMZkzxrYDUX4o7cnuPgU+YrcaYXzsRtLB16I1FR5SHMqga3zGsaSliZADCWo2v8qHWqAYIj8nWCCg==",
- "dev": true,
- "requires": {
- "@eslint-community/regexpp": "^4.4.0",
- "@typescript-eslint/scope-manager": "5.56.0",
- "@typescript-eslint/type-utils": "5.56.0",
- "@typescript-eslint/utils": "5.56.0",
- "debug": "^4.3.4",
- "grapheme-splitter": "^1.0.4",
- "ignore": "^5.2.0",
- "natural-compare-lite": "^1.4.0",
- "semver": "^7.3.7",
- "tsutils": "^3.21.0"
- },
- "dependencies": {
- "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,
- "requires": {
- "yallist": "^4.0.0"
- }
- },
- "semver": {
- "version": "7.3.8",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
- "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
- "dev": true,
- "requires": {
- "lru-cache": "^6.0.0"
- }
- },
- "yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "dev": true
- }
- }
- },
- "@typescript-eslint/parser": {
- "version": "5.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.56.0.tgz",
- "integrity": "sha512-sn1OZmBxUsgxMmR8a8U5QM/Wl+tyqlH//jTqCg8daTAmhAk26L2PFhcqPLlYBhYUJMZJK276qLXlHN3a83o2cg==",
- "dev": true,
- "peer": true,
- "requires": {
- "@typescript-eslint/scope-manager": "5.56.0",
- "@typescript-eslint/types": "5.56.0",
- "@typescript-eslint/typescript-estree": "5.56.0",
- "debug": "^4.3.4"
- }
- },
- "@typescript-eslint/scope-manager": {
- "version": "5.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.56.0.tgz",
- "integrity": "sha512-jGYKyt+iBakD0SA5Ww8vFqGpoV2asSjwt60Gl6YcO8ksQ8s2HlUEyHBMSa38bdLopYqGf7EYQMUIGdT/Luw+sw==",
- "dev": true,
- "requires": {
- "@typescript-eslint/types": "5.56.0",
- "@typescript-eslint/visitor-keys": "5.56.0"
- }
- },
- "@typescript-eslint/type-utils": {
- "version": "5.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.56.0.tgz",
- "integrity": "sha512-8WxgOgJjWRy6m4xg9KoSHPzBNZeQbGlQOH7l2QEhQID/+YseaFxg5J/DLwWSsi9Axj4e/cCiKx7PVzOq38tY4A==",
- "dev": true,
- "requires": {
- "@typescript-eslint/typescript-estree": "5.56.0",
- "@typescript-eslint/utils": "5.56.0",
- "debug": "^4.3.4",
- "tsutils": "^3.21.0"
- }
- },
- "@typescript-eslint/types": {
- "version": "5.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.56.0.tgz",
- "integrity": "sha512-JyAzbTJcIyhuUhogmiu+t79AkdnqgPUEsxMTMc/dCZczGMJQh1MK2wgrju++yMN6AWroVAy2jxyPcPr3SWCq5w==",
- "dev": true
- },
- "@typescript-eslint/typescript-estree": {
- "version": "5.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.56.0.tgz",
- "integrity": "sha512-41CH/GncsLXOJi0jb74SnC7jVPWeVJ0pxQj8bOjH1h2O26jXN3YHKDT1ejkVz5YeTEQPeLCCRY0U2r68tfNOcg==",
- "dev": true,
- "requires": {
- "@typescript-eslint/types": "5.56.0",
- "@typescript-eslint/visitor-keys": "5.56.0",
- "debug": "^4.3.4",
- "globby": "^11.1.0",
- "is-glob": "^4.0.3",
- "semver": "^7.3.7",
- "tsutils": "^3.21.0"
- },
- "dependencies": {
- "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,
- "requires": {
- "yallist": "^4.0.0"
- }
- },
- "semver": {
- "version": "7.3.8",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
- "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
- "dev": true,
- "requires": {
- "lru-cache": "^6.0.0"
- }
- },
- "yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "dev": true
- }
- }
- },
- "@typescript-eslint/utils": {
- "version": "5.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.56.0.tgz",
- "integrity": "sha512-XhZDVdLnUJNtbzaJeDSCIYaM+Tgr59gZGbFuELgF7m0IY03PlciidS7UQNKLE0+WpUTn1GlycEr6Ivb/afjbhA==",
- "dev": true,
- "requires": {
- "@eslint-community/eslint-utils": "^4.2.0",
- "@types/json-schema": "^7.0.9",
- "@types/semver": "^7.3.12",
- "@typescript-eslint/scope-manager": "5.56.0",
- "@typescript-eslint/types": "5.56.0",
- "@typescript-eslint/typescript-estree": "5.56.0",
- "eslint-scope": "^5.1.1",
- "semver": "^7.3.7"
- },
- "dependencies": {
- "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,
- "requires": {
- "yallist": "^4.0.0"
- }
- },
- "semver": {
- "version": "7.3.8",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
- "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
- "dev": true,
- "requires": {
- "lru-cache": "^6.0.0"
- }
- },
- "yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "dev": true
- }
- }
- },
- "@typescript-eslint/visitor-keys": {
- "version": "5.56.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.56.0.tgz",
- "integrity": "sha512-1mFdED7u5bZpX6Xxf5N9U2c18sb+8EvU3tyOIj6LQZ5OOvnmj8BVeNNP603OFPm5KkS1a7IvCIcwrdHXaEMG/Q==",
- "dev": true,
- "requires": {
- "@typescript-eslint/types": "5.56.0",
- "eslint-visitor-keys": "^3.3.0"
- }
- },
- "acorn": {
- "version": "8.8.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz",
- "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==",
- "dev": true
- },
- "acorn-jsx": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
- "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
- "dev": true,
- "requires": {}
- },
- "acorn-walk": {
- "version": "8.2.0",
- "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz",
- "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==",
- "dev": true
- },
- "ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "dev": true,
- "requires": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- }
- },
- "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,
- "requires": {
- "type-fest": "^0.21.3"
- }
- },
- "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
- },
- "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,
- "requires": {
- "color-convert": "^2.0.1"
- }
- },
- "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,
- "requires": {
- "normalize-path": "^3.0.0",
- "picomatch": "^2.0.4"
- }
- },
- "arg": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
- "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
- "dev": true
- },
- "argparse": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
- "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
- "dev": true,
- "requires": {
- "sprintf-js": "~1.0.2"
- }
- },
- "array-buffer-byte-length": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
- "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "is-array-buffer": "^3.0.1"
- }
- },
- "array-includes": {
- "version": "3.1.6",
- "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz",
- "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
- "es-abstract": "^1.20.4",
- "get-intrinsic": "^1.1.3",
- "is-string": "^1.0.7"
- }
- },
- "array-union": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
- "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
- "dev": true
- },
- "array.prototype.flat": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz",
- "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
- "es-abstract": "^1.20.4",
- "es-shim-unscopables": "^1.0.0"
- }
- },
- "array.prototype.flatmap": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz",
- "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
- "es-abstract": "^1.20.4",
- "es-shim-unscopables": "^1.0.0"
- }
- },
- "available-typed-arrays": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
- "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
- "dev": true
- },
- "aws-cdk": {
- "version": "2.68.0",
- "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.68.0.tgz",
- "integrity": "sha512-r+C5M4J3C7RLiixhxsO/W9Kpb5iB0mFshyn5PXT1cGPkDbx23bnWLOab03jG7uHWIWI01DCipHQyTaeXXqvT3A==",
- "dev": true,
- "requires": {
- "fsevents": "2.3.2"
- }
- },
- "aws-cdk-lib": {
- "version": "2.68.0",
- "resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.68.0.tgz",
- "integrity": "sha512-roN3xwzv/GleGG3CaJrf+thdzr9WBzJU4LotumEOs+0cGfeXSta8Pm/cGAeY4kplr5r10QWUovH0fv/bi6Vrbw==",
- "requires": {
- "@aws-cdk/asset-awscli-v1": "^2.2.97",
- "@aws-cdk/asset-kubectl-v20": "^2.1.1",
- "@aws-cdk/asset-node-proxy-agent-v5": "^2.0.77",
- "@balena/dockerignore": "^1.0.2",
- "case": "1.6.3",
- "fs-extra": "^9.1.0",
- "ignore": "^5.2.4",
- "jsonschema": "^1.4.1",
- "minimatch": "^3.1.2",
- "punycode": "^2.3.0",
- "semver": "^7.3.8",
- "yaml": "1.10.2"
- },
- "dependencies": {
- "@balena/dockerignore": {
- "version": "1.0.2",
- "bundled": true
- },
- "at-least-node": {
- "version": "1.0.0",
- "bundled": true
- },
- "balanced-match": {
- "version": "1.0.2",
- "bundled": true
- },
- "brace-expansion": {
- "version": "1.1.11",
- "bundled": true,
- "requires": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "case": {
- "version": "1.6.3",
- "bundled": true
- },
- "concat-map": {
- "version": "0.0.1",
- "bundled": true
- },
- "fs-extra": {
- "version": "9.1.0",
- "bundled": true,
- "requires": {
- "at-least-node": "^1.0.0",
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- }
- },
- "graceful-fs": {
- "version": "4.2.10",
- "bundled": true
- },
- "ignore": {
- "version": "5.2.4",
- "bundled": true
- },
- "jsonfile": {
- "version": "6.1.0",
- "bundled": true,
- "requires": {
- "graceful-fs": "^4.1.6",
- "universalify": "^2.0.0"
- }
- },
- "jsonschema": {
- "version": "1.4.1",
- "bundled": true
- },
- "lru-cache": {
- "version": "6.0.0",
- "bundled": true,
- "requires": {
- "yallist": "^4.0.0"
- }
- },
- "minimatch": {
- "version": "3.1.2",
- "bundled": true,
- "requires": {
- "brace-expansion": "^1.1.7"
- }
- },
- "punycode": {
- "version": "2.3.0",
- "bundled": true
- },
- "semver": {
- "version": "7.3.8",
- "bundled": true,
- "requires": {
- "lru-cache": "^6.0.0"
- }
- },
- "universalify": {
- "version": "2.0.0",
- "bundled": true
- },
- "yallist": {
- "version": "4.0.0",
- "bundled": true
- },
- "yaml": {
- "version": "1.10.2",
- "bundled": true
- }
- }
- },
- "babel-jest": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.3.1.tgz",
- "integrity": "sha512-aard+xnMoxgjwV70t0L6wkW/3HQQtV+O0PEimxKgzNqCJnbYmroPojdP2tqKSOAt8QAKV/uSZU8851M7B5+fcA==",
- "dev": true,
- "requires": {
- "@jest/transform": "^29.3.1",
- "@types/babel__core": "^7.1.14",
- "babel-plugin-istanbul": "^6.1.1",
- "babel-preset-jest": "^29.2.0",
- "chalk": "^4.0.0",
- "graceful-fs": "^4.2.9",
- "slash": "^3.0.0"
- }
- },
- "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,
- "requires": {
- "@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"
- }
- },
- "babel-plugin-jest-hoist": {
- "version": "29.2.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.2.0.tgz",
- "integrity": "sha512-TnspP2WNiR3GLfCsUNHqeXw0RoQ2f9U5hQ5L3XFpwuO8htQmSrhh8qsB6vi5Yi8+kuynN1yjDjQsPfkebmB6ZA==",
- "dev": true,
- "requires": {
- "@babel/template": "^7.3.3",
- "@babel/types": "^7.3.3",
- "@types/babel__core": "^7.1.14",
- "@types/babel__traverse": "^7.0.6"
- }
- },
- "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,
- "requires": {
- "@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"
- }
- },
- "babel-preset-jest": {
- "version": "29.2.0",
- "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.2.0.tgz",
- "integrity": "sha512-z9JmMJppMxNv8N7fNRHvhMg9cvIkMxQBXgFkane3yKVEvEOP+kB50lk8DFRvF9PGqbyXxlmebKWhuDORO8RgdA==",
- "dev": true,
- "requires": {
- "babel-plugin-jest-hoist": "^29.2.0",
- "babel-preset-current-node-syntax": "^1.0.0"
- }
- },
- "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
- },
- "bowser": {
- "version": "2.11.0",
- "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz",
- "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA=="
- },
- "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,
- "requires": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
- "dev": true,
- "requires": {
- "fill-range": "^7.0.1"
- }
- },
- "browserslist": {
- "version": "4.21.4",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
- "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==",
- "dev": true,
- "requires": {
- "caniuse-lite": "^1.0.30001400",
- "electron-to-chromium": "^1.4.251",
- "node-releases": "^2.0.6",
- "update-browserslist-db": "^1.0.9"
- }
- },
- "bs-logger": {
- "version": "0.2.6",
- "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz",
- "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==",
- "dev": true,
- "requires": {
- "fast-json-stable-stringify": "2.x"
- }
- },
- "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,
- "requires": {
- "node-int64": "^0.4.0"
- }
- },
- "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=="
- },
- "call-bind": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
- "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
- "dev": true,
- "requires": {
- "function-bind": "^1.1.1",
- "get-intrinsic": "^1.0.2"
- }
- },
- "callsites": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
- "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
- "dev": true
- },
- "camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
- "dev": true
- },
- "caniuse-lite": {
- "version": "1.0.30001442",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001442.tgz",
- "integrity": "sha512-239m03Pqy0hwxYPYR5JwOIxRJfLTWtle9FV8zosfV5pHg+/51uD4nxcUlM8+mWWGfwKtt8lJNHnD3cWw9VZ6ow==",
- "dev": true
- },
- "cdk-nag": {
- "version": "2.22.23",
- "resolved": "https://registry.npmjs.org/cdk-nag/-/cdk-nag-2.22.23.tgz",
- "integrity": "sha512-bEV7AMqnFBMm/VBdAGgsGd3cKuNNhkriygsb8N7ewO2cY4moQ4RvcAGPxbssm4gfVfanTG8+5XLazYnDsv443Q==",
- "requires": {}
- },
- "chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
- "requires": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- }
- },
- "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
- },
- "ci-info": {
- "version": "3.7.1",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.1.tgz",
- "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==",
- "dev": true
- },
- "cjs-module-lexer": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz",
- "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==",
- "dev": true
- },
- "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,
- "requires": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.1",
- "wrap-ansi": "^7.0.0"
- }
- },
- "co": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
- "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
- "dev": true
- },
- "collect-v8-coverage": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz",
- "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==",
- "dev": true
- },
- "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,
- "requires": {
- "color-name": "~1.1.4"
- }
- },
- "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
- },
- "concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "dev": true
- },
- "constructs": {
- "version": "10.1.216",
- "resolved": "https://registry.npmjs.org/constructs/-/constructs-10.1.216.tgz",
- "integrity": "sha512-Nx/Pzuyy46Bc5LFu3XPSmTKNcjN4ChQ/R3syOb7bJLfQ5VhJn+o0aCKBVwnbuF1av0YCG6IaDz8fdtWhjefJjA=="
- },
- "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
- },
- "create-require": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
- "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
- "dev": true
- },
- "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,
- "requires": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
- }
- },
- "debug": {
- "version": "4.3.4",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
- "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
- "dev": true,
- "requires": {
- "ms": "2.1.2"
- }
- },
- "dedent": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
- "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==",
- "dev": true
- },
- "deep-is": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
- "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
- "dev": true
- },
- "deepmerge": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
- "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
- "dev": true
- },
- "define-properties": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz",
- "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==",
- "dev": true,
- "requires": {
- "has-property-descriptors": "^1.0.0",
- "object-keys": "^1.1.1"
- }
- },
- "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
- },
- "diff-sequences": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz",
- "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==",
- "dev": true
- },
- "dir-glob": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
- "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
- "dev": true,
- "requires": {
- "path-type": "^4.0.0"
- }
- },
- "doctrine": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
- "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
- "dev": true,
- "requires": {
- "esutils": "^2.0.2"
- }
- },
- "electron-to-chromium": {
- "version": "1.4.284",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz",
- "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==",
- "dev": true
- },
- "emittery": {
- "version": "0.13.1",
- "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
- "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==",
- "dev": true
- },
- "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
- },
- "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,
- "requires": {
- "is-arrayish": "^0.2.1"
- }
- },
- "es-abstract": {
- "version": "1.21.2",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz",
- "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==",
- "dev": true,
- "requires": {
- "array-buffer-byte-length": "^1.0.0",
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.2",
- "es-set-tostringtag": "^2.0.1",
- "es-to-primitive": "^1.2.1",
- "function.prototype.name": "^1.1.5",
- "get-intrinsic": "^1.2.0",
- "get-symbol-description": "^1.0.0",
- "globalthis": "^1.0.3",
- "gopd": "^1.0.1",
- "has": "^1.0.3",
- "has-property-descriptors": "^1.0.0",
- "has-proto": "^1.0.1",
- "has-symbols": "^1.0.3",
- "internal-slot": "^1.0.5",
- "is-array-buffer": "^3.0.2",
- "is-callable": "^1.2.7",
- "is-negative-zero": "^2.0.2",
- "is-regex": "^1.1.4",
- "is-shared-array-buffer": "^1.0.2",
- "is-string": "^1.0.7",
- "is-typed-array": "^1.1.10",
- "is-weakref": "^1.0.2",
- "object-inspect": "^1.12.3",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.4",
- "regexp.prototype.flags": "^1.4.3",
- "safe-regex-test": "^1.0.0",
- "string.prototype.trim": "^1.2.7",
- "string.prototype.trimend": "^1.0.6",
- "string.prototype.trimstart": "^1.0.6",
- "typed-array-length": "^1.0.4",
- "unbox-primitive": "^1.0.2",
- "which-typed-array": "^1.1.9"
- }
- },
- "es-set-tostringtag": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
- "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==",
- "dev": true,
- "requires": {
- "get-intrinsic": "^1.1.3",
- "has": "^1.0.3",
- "has-tostringtag": "^1.0.0"
- }
- },
- "es-shim-unscopables": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz",
- "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==",
- "dev": true,
- "requires": {
- "has": "^1.0.3"
- }
- },
- "es-to-primitive": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
- "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
- "dev": true,
- "requires": {
- "is-callable": "^1.1.4",
- "is-date-object": "^1.0.1",
- "is-symbol": "^1.0.2"
- }
- },
- "escalade": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
- "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
- "dev": true
- },
- "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
- },
- "eslint": {
- "version": "8.36.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz",
- "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==",
- "dev": true,
- "requires": {
- "@eslint-community/eslint-utils": "^4.2.0",
- "@eslint-community/regexpp": "^4.4.0",
- "@eslint/eslintrc": "^2.0.1",
- "@eslint/js": "8.36.0",
- "@humanwhocodes/config-array": "^0.11.8",
- "@humanwhocodes/module-importer": "^1.0.1",
- "@nodelib/fs.walk": "^1.2.8",
- "ajv": "^6.10.0",
- "chalk": "^4.0.0",
- "cross-spawn": "^7.0.2",
- "debug": "^4.3.2",
- "doctrine": "^3.0.0",
- "escape-string-regexp": "^4.0.0",
- "eslint-scope": "^7.1.1",
- "eslint-visitor-keys": "^3.3.0",
- "espree": "^9.5.0",
- "esquery": "^1.4.2",
- "esutils": "^2.0.2",
- "fast-deep-equal": "^3.1.3",
- "file-entry-cache": "^6.0.1",
- "find-up": "^5.0.0",
- "glob-parent": "^6.0.2",
- "globals": "^13.19.0",
- "grapheme-splitter": "^1.0.4",
- "ignore": "^5.2.0",
- "import-fresh": "^3.0.0",
- "imurmurhash": "^0.1.4",
- "is-glob": "^4.0.0",
- "is-path-inside": "^3.0.3",
- "js-sdsl": "^4.1.4",
- "js-yaml": "^4.1.0",
- "json-stable-stringify-without-jsonify": "^1.0.1",
- "levn": "^0.4.1",
- "lodash.merge": "^4.6.2",
- "minimatch": "^3.1.2",
- "natural-compare": "^1.4.0",
- "optionator": "^0.9.1",
- "strip-ansi": "^6.0.1",
- "strip-json-comments": "^3.1.0",
- "text-table": "^0.2.0"
- },
- "dependencies": {
- "argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true
- },
- "escape-string-regexp": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
- "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
- "dev": true
- },
- "eslint-scope": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
- "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
- "dev": true,
- "requires": {
- "esrecurse": "^4.3.0",
- "estraverse": "^5.2.0"
- }
- },
- "estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
- "dev": true
- },
- "find-up": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
- "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
- "dev": true,
- "requires": {
- "locate-path": "^6.0.0",
- "path-exists": "^4.0.0"
- }
- },
- "globals": {
- "version": "13.20.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
- "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
- "dev": true,
- "requires": {
- "type-fest": "^0.20.2"
- }
- },
- "js-yaml": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
- "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
- "dev": true,
- "requires": {
- "argparse": "^2.0.1"
- }
- },
- "locate-path": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
- "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
- "dev": true,
- "requires": {
- "p-locate": "^5.0.0"
- }
- },
- "p-locate": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
- "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
- "dev": true,
- "requires": {
- "p-limit": "^3.0.2"
- }
- },
- "type-fest": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
- "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
- "dev": true
- }
- }
- },
- "eslint-config-prettier": {
- "version": "8.8.0",
- "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz",
- "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==",
- "dev": true,
- "requires": {}
- },
- "eslint-import-resolver-node": {
- "version": "0.3.7",
- "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz",
- "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==",
- "dev": true,
- "requires": {
- "debug": "^3.2.7",
- "is-core-module": "^2.11.0",
- "resolve": "^1.22.1"
- },
- "dependencies": {
- "debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
- "dev": true,
- "requires": {
- "ms": "^2.1.1"
- }
- }
- }
- },
- "eslint-module-utils": {
- "version": "2.7.4",
- "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz",
- "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==",
- "dev": true,
- "requires": {
- "debug": "^3.2.7"
- },
- "dependencies": {
- "debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
- "dev": true,
- "requires": {
- "ms": "^2.1.1"
- }
- }
- }
- },
- "eslint-plugin-header": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-header/-/eslint-plugin-header-3.1.1.tgz",
- "integrity": "sha512-9vlKxuJ4qf793CmeeSrZUvVClw6amtpghq3CuWcB5cUNnWHQhgcqy5eF8oVKFk1G3Y/CbchGfEaw3wiIJaNmVg==",
- "dev": true,
- "requires": {}
- },
- "eslint-plugin-import": {
- "version": "2.27.5",
- "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz",
- "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==",
- "dev": true,
- "requires": {
- "array-includes": "^3.1.6",
- "array.prototype.flat": "^1.3.1",
- "array.prototype.flatmap": "^1.3.1",
- "debug": "^3.2.7",
- "doctrine": "^2.1.0",
- "eslint-import-resolver-node": "^0.3.7",
- "eslint-module-utils": "^2.7.4",
- "has": "^1.0.3",
- "is-core-module": "^2.11.0",
- "is-glob": "^4.0.3",
- "minimatch": "^3.1.2",
- "object.values": "^1.1.6",
- "resolve": "^1.22.1",
- "semver": "^6.3.0",
- "tsconfig-paths": "^3.14.1"
- },
- "dependencies": {
- "debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
- "dev": true,
- "requires": {
- "ms": "^2.1.1"
- }
- },
- "doctrine": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
- "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
- "dev": true,
- "requires": {
- "esutils": "^2.0.2"
- }
- }
- }
- },
- "eslint-plugin-prettier": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz",
- "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==",
- "dev": true,
- "requires": {
- "prettier-linter-helpers": "^1.0.0"
- }
- },
- "eslint-scope": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
- "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
- "dev": true,
- "requires": {
- "esrecurse": "^4.3.0",
- "estraverse": "^4.1.1"
- }
- },
- "eslint-visitor-keys": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
- "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
- "dev": true
- },
- "espree": {
- "version": "9.5.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz",
- "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==",
- "dev": true,
- "requires": {
- "acorn": "^8.8.0",
- "acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^3.3.0"
- }
- },
- "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
- },
- "esquery": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
- "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
- "dev": true,
- "requires": {
- "estraverse": "^5.1.0"
- },
- "dependencies": {
- "estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
- "dev": true
- }
- }
- },
- "esrecurse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
- "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
- "dev": true,
- "requires": {
- "estraverse": "^5.2.0"
- },
- "dependencies": {
- "estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
- "dev": true
- }
- }
- },
- "estraverse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
- "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
- "dev": true
- },
- "esutils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
- "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
- "dev": true
- },
- "execa": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
- "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
- "dev": true,
- "requires": {
- "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"
- }
- },
- "exit": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
- "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==",
- "dev": true
- },
- "expect": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/expect/-/expect-29.3.1.tgz",
- "integrity": "sha512-gGb1yTgU30Q0O/tQq+z30KBWv24ApkMgFUpvKBkyLUBL68Wv8dHdJxTBZFl/iT8K/bqDHvUYRH6IIN3rToopPA==",
- "dev": true,
- "requires": {
- "@jest/expect-utils": "^29.3.1",
- "jest-get-type": "^29.2.0",
- "jest-matcher-utils": "^29.3.1",
- "jest-message-util": "^29.3.1",
- "jest-util": "^29.3.1"
- }
- },
- "fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "dev": true
- },
- "fast-diff": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
- "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
- "dev": true
- },
- "fast-glob": {
- "version": "3.2.12",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
- "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
- "dev": true,
- "requires": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.4"
- },
- "dependencies": {
- "glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "requires": {
- "is-glob": "^4.0.1"
- }
- }
- }
- },
- "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
- },
- "fast-levenshtein": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
- "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
- "dev": true
- },
- "fast-xml-parser": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.1.2.tgz",
- "integrity": "sha512-CDYeykkle1LiA/uqQyNwYpFbyF6Axec6YapmpUP+/RHWIoR1zKjocdvNaTsxCxZzQ6v9MLXaSYm9Qq0thv0DHg==",
- "requires": {
- "strnum": "^1.0.5"
- }
- },
- "fastq": {
- "version": "1.15.0",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
- "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
- "dev": true,
- "requires": {
- "reusify": "^1.0.4"
- }
- },
- "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,
- "requires": {
- "bser": "2.1.1"
- }
- },
- "file-entry-cache": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
- "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
- "dev": true,
- "requires": {
- "flat-cache": "^3.0.4"
- }
- },
- "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,
- "requires": {
- "to-regex-range": "^5.0.1"
- }
- },
- "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,
- "requires": {
- "locate-path": "^5.0.0",
- "path-exists": "^4.0.0"
- }
- },
- "flat-cache": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
- "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
- "dev": true,
- "requires": {
- "flatted": "^3.1.0",
- "rimraf": "^3.0.2"
- }
- },
- "flatted": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
- "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
- "dev": true
- },
- "for-each": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
- "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
- "dev": true,
- "requires": {
- "is-callable": "^1.1.3"
- }
- },
- "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
- },
- "fsevents": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
- "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
- "dev": true,
- "optional": true
- },
- "function-bind": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
- "dev": true
- },
- "function.prototype.name": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
- "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.3",
- "es-abstract": "^1.19.0",
- "functions-have-names": "^1.2.2"
- }
- },
- "functions-have-names": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
- "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
- "dev": true
- },
- "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
- },
- "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
- },
- "get-intrinsic": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz",
- "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==",
- "dev": true,
- "requires": {
- "function-bind": "^1.1.1",
- "has": "^1.0.3",
- "has-symbols": "^1.0.3"
- }
- },
- "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
- },
- "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
- },
- "get-symbol-description": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
- "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.1.1"
- }
- },
- "glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "dev": true,
- "requires": {
- "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"
- }
- },
- "glob-parent": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
- "requires": {
- "is-glob": "^4.0.3"
- }
- },
- "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
- },
- "globalthis": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
- "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
- "dev": true,
- "requires": {
- "define-properties": "^1.1.3"
- }
- },
- "globby": {
- "version": "11.1.0",
- "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
- "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
- "dev": true,
- "requires": {
- "array-union": "^2.1.0",
- "dir-glob": "^3.0.1",
- "fast-glob": "^3.2.9",
- "ignore": "^5.2.0",
- "merge2": "^1.4.1",
- "slash": "^3.0.0"
- }
- },
- "gopd": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
- "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
- "dev": true,
- "requires": {
- "get-intrinsic": "^1.1.3"
- }
- },
- "graceful-fs": {
- "version": "4.2.10",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
- "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
- "dev": true
- },
- "grapheme-splitter": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
- "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
- "dev": true
- },
- "has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "dev": true,
- "requires": {
- "function-bind": "^1.1.1"
- }
- },
- "has-bigints": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
- "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
- "dev": true
- },
- "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
- },
- "has-property-descriptors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
- "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
- "dev": true,
- "requires": {
- "get-intrinsic": "^1.1.1"
- }
- },
- "has-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
- "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
- "dev": true
- },
- "has-symbols": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
- "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
- "dev": true
- },
- "has-tostringtag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
- "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
- "dev": true,
- "requires": {
- "has-symbols": "^1.0.2"
- }
- },
- "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
- },
- "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
- },
- "ignore": {
- "version": "5.2.4",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
- "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
- "dev": true
- },
- "import-fresh": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
- "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
- "dev": true,
- "requires": {
- "parent-module": "^1.0.0",
- "resolve-from": "^4.0.0"
- },
- "dependencies": {
- "resolve-from": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
- "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
- "dev": true
- }
- }
- },
- "import-local": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz",
- "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==",
- "dev": true,
- "requires": {
- "pkg-dir": "^4.2.0",
- "resolve-cwd": "^3.0.0"
- }
- },
- "imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
- "dev": true
- },
- "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,
- "requires": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "dev": true
- },
- "internal-slot": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz",
- "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==",
- "dev": true,
- "requires": {
- "get-intrinsic": "^1.2.0",
- "has": "^1.0.3",
- "side-channel": "^1.0.4"
- }
- },
- "is-array-buffer": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
- "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.2.0",
- "is-typed-array": "^1.1.10"
- }
- },
- "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
- },
- "is-bigint": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
- "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
- "dev": true,
- "requires": {
- "has-bigints": "^1.0.1"
- }
- },
- "is-boolean-object": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
- "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "has-tostringtag": "^1.0.0"
- }
- },
- "is-callable": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
- "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
- "dev": true
- },
- "is-core-module": {
- "version": "2.11.0",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
- "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
- "dev": true,
- "requires": {
- "has": "^1.0.3"
- }
- },
- "is-date-object": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
- "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
- "dev": true,
- "requires": {
- "has-tostringtag": "^1.0.0"
- }
- },
- "is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true
- },
- "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
- },
- "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
- },
- "is-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
- "requires": {
- "is-extglob": "^2.1.1"
- }
- },
- "is-negative-zero": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
- "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
- "dev": true
- },
- "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
- },
- "is-number-object": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
- "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
- "dev": true,
- "requires": {
- "has-tostringtag": "^1.0.0"
- }
- },
- "is-path-inside": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
- "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
- "dev": true
- },
- "is-regex": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
- "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "has-tostringtag": "^1.0.0"
- }
- },
- "is-shared-array-buffer": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
- "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2"
- }
- },
- "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
- },
- "is-string": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
- "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
- "dev": true,
- "requires": {
- "has-tostringtag": "^1.0.0"
- }
- },
- "is-symbol": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
- "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
- "dev": true,
- "requires": {
- "has-symbols": "^1.0.2"
- }
- },
- "is-typed-array": {
- "version": "1.1.10",
- "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz",
- "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==",
- "dev": true,
- "requires": {
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.2",
- "for-each": "^0.3.3",
- "gopd": "^1.0.1",
- "has-tostringtag": "^1.0.0"
- }
- },
- "is-weakref": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
- "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2"
- }
- },
- "isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true
- },
- "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
- },
- "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,
- "requires": {
- "@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"
- }
- },
- "istanbul-lib-report": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
- "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==",
- "dev": true,
- "requires": {
- "istanbul-lib-coverage": "^3.0.0",
- "make-dir": "^3.0.0",
- "supports-color": "^7.1.0"
- }
- },
- "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,
- "requires": {
- "debug": "^4.1.1",
- "istanbul-lib-coverage": "^3.0.0",
- "source-map": "^0.6.1"
- }
- },
- "istanbul-reports": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz",
- "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==",
- "dev": true,
- "requires": {
- "html-escaper": "^2.0.0",
- "istanbul-lib-report": "^3.0.0"
- }
- },
- "jest": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest/-/jest-29.3.1.tgz",
- "integrity": "sha512-6iWfL5DTT0Np6UYs/y5Niu7WIfNv/wRTtN5RSXt2DIEft3dx3zPuw/3WJQBCJfmEzvDiEKwoqMbGD9n49+qLSA==",
- "dev": true,
- "requires": {
- "@jest/core": "^29.3.1",
- "@jest/types": "^29.3.1",
- "import-local": "^3.0.2",
- "jest-cli": "^29.3.1"
- }
- },
- "jest-changed-files": {
- "version": "29.2.0",
- "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.2.0.tgz",
- "integrity": "sha512-qPVmLLyBmvF5HJrY7krDisx6Voi8DmlV3GZYX0aFNbaQsZeoz1hfxcCMbqDGuQCxU1dJy9eYc2xscE8QrCCYaA==",
- "dev": true,
- "requires": {
- "execa": "^5.0.0",
- "p-limit": "^3.1.0"
- }
- },
- "jest-circus": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.3.1.tgz",
- "integrity": "sha512-wpr26sEvwb3qQQbdlmei+gzp6yoSSoSL6GsLPxnuayZSMrSd5Ka7IjAvatpIernBvT2+Ic6RLTg+jSebScmasg==",
- "dev": true,
- "requires": {
- "@jest/environment": "^29.3.1",
- "@jest/expect": "^29.3.1",
- "@jest/test-result": "^29.3.1",
- "@jest/types": "^29.3.1",
- "@types/node": "*",
- "chalk": "^4.0.0",
- "co": "^4.6.0",
- "dedent": "^0.7.0",
- "is-generator-fn": "^2.0.0",
- "jest-each": "^29.3.1",
- "jest-matcher-utils": "^29.3.1",
- "jest-message-util": "^29.3.1",
- "jest-runtime": "^29.3.1",
- "jest-snapshot": "^29.3.1",
- "jest-util": "^29.3.1",
- "p-limit": "^3.1.0",
- "pretty-format": "^29.3.1",
- "slash": "^3.0.0",
- "stack-utils": "^2.0.3"
- },
- "dependencies": {
- "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
- },
- "pretty-format": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz",
- "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==",
- "dev": true,
- "requires": {
- "@jest/schemas": "^29.0.0",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- }
- },
- "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
- }
- }
- },
- "jest-cli": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.3.1.tgz",
- "integrity": "sha512-TO/ewvwyvPOiBBuWZ0gm04z3WWP8TIK8acgPzE4IxgsLKQgb377NYGrQLc3Wl/7ndWzIH2CDNNsUjGxwLL43VQ==",
- "dev": true,
- "requires": {
- "@jest/core": "^29.3.1",
- "@jest/test-result": "^29.3.1",
- "@jest/types": "^29.3.1",
- "chalk": "^4.0.0",
- "exit": "^0.1.2",
- "graceful-fs": "^4.2.9",
- "import-local": "^3.0.2",
- "jest-config": "^29.3.1",
- "jest-util": "^29.3.1",
- "jest-validate": "^29.3.1",
- "prompts": "^2.0.1",
- "yargs": "^17.3.1"
- }
- },
- "jest-config": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.3.1.tgz",
- "integrity": "sha512-y0tFHdj2WnTEhxmGUK1T7fgLen7YK4RtfvpLFBXfQkh2eMJAQq24Vx9472lvn5wg0MAO6B+iPfJfzdR9hJYalg==",
- "dev": true,
- "requires": {
- "@babel/core": "^7.11.6",
- "@jest/test-sequencer": "^29.3.1",
- "@jest/types": "^29.3.1",
- "babel-jest": "^29.3.1",
- "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.3.1",
- "jest-environment-node": "^29.3.1",
- "jest-get-type": "^29.2.0",
- "jest-regex-util": "^29.2.0",
- "jest-resolve": "^29.3.1",
- "jest-runner": "^29.3.1",
- "jest-util": "^29.3.1",
- "jest-validate": "^29.3.1",
- "micromatch": "^4.0.4",
- "parse-json": "^5.2.0",
- "pretty-format": "^29.3.1",
- "slash": "^3.0.0",
- "strip-json-comments": "^3.1.1"
- },
- "dependencies": {
- "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
- },
- "pretty-format": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz",
- "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==",
- "dev": true,
- "requires": {
- "@jest/schemas": "^29.0.0",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- }
- },
- "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
- }
- }
- },
- "jest-diff": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz",
- "integrity": "sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==",
- "dev": true,
- "requires": {
- "chalk": "^4.0.0",
- "diff-sequences": "^26.6.2",
- "jest-get-type": "^26.3.0",
- "pretty-format": "^26.6.2"
- },
- "dependencies": {
- "jest-get-type": {
- "version": "26.3.0",
- "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz",
- "integrity": "sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==",
- "dev": true
- }
- }
- },
- "jest-docblock": {
- "version": "29.2.0",
- "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.2.0.tgz",
- "integrity": "sha512-bkxUsxTgWQGbXV5IENmfiIuqZhJcyvF7tU4zJ/7ioTutdz4ToB5Yx6JOFBpgI+TphRY4lhOyCWGNH/QFQh5T6A==",
- "dev": true,
- "requires": {
- "detect-newline": "^3.0.0"
- }
- },
- "jest-each": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.3.1.tgz",
- "integrity": "sha512-qrZH7PmFB9rEzCSl00BWjZYuS1BSOH8lLuC0azQE9lQrAx3PWGKHTDudQiOSwIy5dGAJh7KA0ScYlCP7JxvFYA==",
- "dev": true,
- "requires": {
- "@jest/types": "^29.3.1",
- "chalk": "^4.0.0",
- "jest-get-type": "^29.2.0",
- "jest-util": "^29.3.1",
- "pretty-format": "^29.3.1"
- },
- "dependencies": {
- "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
- },
- "pretty-format": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz",
- "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==",
- "dev": true,
- "requires": {
- "@jest/schemas": "^29.0.0",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- }
- },
- "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
- }
- }
- },
- "jest-environment-node": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.3.1.tgz",
- "integrity": "sha512-xm2THL18Xf5sIHoU7OThBPtuH6Lerd+Y1NLYiZJlkE3hbE+7N7r8uvHIl/FkZ5ymKXJe/11SQuf3fv4v6rUMag==",
- "dev": true,
- "requires": {
- "@jest/environment": "^29.3.1",
- "@jest/fake-timers": "^29.3.1",
- "@jest/types": "^29.3.1",
- "@types/node": "*",
- "jest-mock": "^29.3.1",
- "jest-util": "^29.3.1"
- }
- },
- "jest-extended": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/jest-extended/-/jest-extended-3.2.4.tgz",
- "integrity": "sha512-lSEYhSmvXZG/7YXI7KO3LpiUiQ90gi5giwCJNDMMsX5a+/NZhdbQF2G4ALOBN+KcXVT3H6FPVPohAuMXooaLTQ==",
- "dev": true,
- "requires": {
- "jest-diff": "^29.0.0",
- "jest-get-type": "^29.0.0"
- },
- "dependencies": {
- "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
- },
- "diff-sequences": {
- "version": "29.4.3",
- "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz",
- "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==",
- "dev": true
- },
- "jest-diff": {
- "version": "29.5.0",
- "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz",
- "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==",
- "dev": true,
- "requires": {
- "chalk": "^4.0.0",
- "diff-sequences": "^29.4.3",
- "jest-get-type": "^29.4.3",
- "pretty-format": "^29.5.0"
- }
- },
- "pretty-format": {
- "version": "29.5.0",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz",
- "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==",
- "dev": true,
- "requires": {
- "@jest/schemas": "^29.4.3",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- }
- },
- "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
- }
- }
- },
- "jest-get-type": {
- "version": "29.4.3",
- "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz",
- "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==",
- "dev": true
- },
- "jest-haste-map": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.3.1.tgz",
- "integrity": "sha512-/FFtvoG1xjbbPXQLFef+WSU4yrc0fc0Dds6aRPBojUid7qlPqZvxdUBA03HW0fnVHXVCnCdkuoghYItKNzc/0A==",
- "dev": true,
- "requires": {
- "@jest/types": "^29.3.1",
- "@types/graceful-fs": "^4.1.3",
- "@types/node": "*",
- "anymatch": "^3.0.3",
- "fb-watchman": "^2.0.0",
- "fsevents": "^2.3.2",
- "graceful-fs": "^4.2.9",
- "jest-regex-util": "^29.2.0",
- "jest-util": "^29.3.1",
- "jest-worker": "^29.3.1",
- "micromatch": "^4.0.4",
- "walker": "^1.0.8"
- }
- },
- "jest-junit": {
- "version": "15.0.0",
- "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-15.0.0.tgz",
- "integrity": "sha512-Z5sVX0Ag3HZdMUnD5DFlG+1gciIFSy7yIVPhOdGUi8YJaI9iLvvBb530gtQL2CHmv0JJeiwRZenr0VrSR7frvg==",
- "dev": true,
- "requires": {
- "mkdirp": "^1.0.4",
- "strip-ansi": "^6.0.1",
- "uuid": "^8.3.2",
- "xml": "^1.0.1"
- }
- },
- "jest-leak-detector": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.3.1.tgz",
- "integrity": "sha512-3DA/VVXj4zFOPagGkuqHnSQf1GZBmmlagpguxEERO6Pla2g84Q1MaVIB3YMxgUaFIaYag8ZnTyQgiZ35YEqAQA==",
- "dev": true,
- "requires": {
- "jest-get-type": "^29.2.0",
- "pretty-format": "^29.3.1"
- },
- "dependencies": {
- "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
- },
- "pretty-format": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz",
- "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==",
- "dev": true,
- "requires": {
- "@jest/schemas": "^29.0.0",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- }
- },
- "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
- }
- }
- },
- "jest-matcher-utils": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.3.1.tgz",
- "integrity": "sha512-fkRMZUAScup3txIKfMe3AIZZmPEjWEdsPJFK3AIy5qRohWqQFg1qrmKfYXR9qEkNc7OdAu2N4KPHibEmy4HPeQ==",
- "dev": true,
- "requires": {
- "chalk": "^4.0.0",
- "jest-diff": "^29.3.1",
- "jest-get-type": "^29.2.0",
- "pretty-format": "^29.3.1"
- },
- "dependencies": {
- "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
- },
- "diff-sequences": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.3.1.tgz",
- "integrity": "sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==",
- "dev": true
- },
- "jest-diff": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.3.1.tgz",
- "integrity": "sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw==",
- "dev": true,
- "requires": {
- "chalk": "^4.0.0",
- "diff-sequences": "^29.3.1",
- "jest-get-type": "^29.2.0",
- "pretty-format": "^29.3.1"
- }
- },
- "pretty-format": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz",
- "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==",
- "dev": true,
- "requires": {
- "@jest/schemas": "^29.0.0",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- }
- },
- "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
- }
- }
- },
- "jest-message-util": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.3.1.tgz",
- "integrity": "sha512-lMJTbgNcDm5z+6KDxWtqOFWlGQxD6XaYwBqHR8kmpkP+WWWG90I35kdtQHY67Ay5CSuydkTBbJG+tH9JShFCyA==",
- "dev": true,
- "requires": {
- "@babel/code-frame": "^7.12.13",
- "@jest/types": "^29.3.1",
- "@types/stack-utils": "^2.0.0",
- "chalk": "^4.0.0",
- "graceful-fs": "^4.2.9",
- "micromatch": "^4.0.4",
- "pretty-format": "^29.3.1",
- "slash": "^3.0.0",
- "stack-utils": "^2.0.3"
- },
- "dependencies": {
- "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
- },
- "pretty-format": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz",
- "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==",
- "dev": true,
- "requires": {
- "@jest/schemas": "^29.0.0",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- }
- },
- "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
- }
- }
- },
- "jest-mock": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.3.1.tgz",
- "integrity": "sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA==",
- "dev": true,
- "requires": {
- "@jest/types": "^29.3.1",
- "@types/node": "*",
- "jest-util": "^29.3.1"
- }
- },
- "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,
- "requires": {}
- },
- "jest-regex-util": {
- "version": "29.2.0",
- "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.2.0.tgz",
- "integrity": "sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA==",
- "dev": true
- },
- "jest-resolve": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.3.1.tgz",
- "integrity": "sha512-amXJgH/Ng712w3Uz5gqzFBBjxV8WFLSmNjoreBGMqxgCz5cH7swmBZzgBaCIOsvb0NbpJ0vgaSFdJqMdT+rADw==",
- "dev": true,
- "requires": {
- "chalk": "^4.0.0",
- "graceful-fs": "^4.2.9",
- "jest-haste-map": "^29.3.1",
- "jest-pnp-resolver": "^1.2.2",
- "jest-util": "^29.3.1",
- "jest-validate": "^29.3.1",
- "resolve": "^1.20.0",
- "resolve.exports": "^1.1.0",
- "slash": "^3.0.0"
- }
- },
- "jest-resolve-dependencies": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.3.1.tgz",
- "integrity": "sha512-Vk0cYq0byRw2WluNmNWGqPeRnZ3p3hHmjJMp2dyyZeYIfiBskwq4rpiuGFR6QGAdbj58WC7HN4hQHjf2mpvrLA==",
- "dev": true,
- "requires": {
- "jest-regex-util": "^29.2.0",
- "jest-snapshot": "^29.3.1"
- }
- },
- "jest-runner": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.3.1.tgz",
- "integrity": "sha512-oFvcwRNrKMtE6u9+AQPMATxFcTySyKfLhvso7Sdk/rNpbhg4g2GAGCopiInk1OP4q6gz3n6MajW4+fnHWlU3bA==",
- "dev": true,
- "requires": {
- "@jest/console": "^29.3.1",
- "@jest/environment": "^29.3.1",
- "@jest/test-result": "^29.3.1",
- "@jest/transform": "^29.3.1",
- "@jest/types": "^29.3.1",
- "@types/node": "*",
- "chalk": "^4.0.0",
- "emittery": "^0.13.1",
- "graceful-fs": "^4.2.9",
- "jest-docblock": "^29.2.0",
- "jest-environment-node": "^29.3.1",
- "jest-haste-map": "^29.3.1",
- "jest-leak-detector": "^29.3.1",
- "jest-message-util": "^29.3.1",
- "jest-resolve": "^29.3.1",
- "jest-runtime": "^29.3.1",
- "jest-util": "^29.3.1",
- "jest-watcher": "^29.3.1",
- "jest-worker": "^29.3.1",
- "p-limit": "^3.1.0",
- "source-map-support": "0.5.13"
- },
- "dependencies": {
- "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,
- "requires": {
- "buffer-from": "^1.0.0",
- "source-map": "^0.6.0"
- }
- }
- }
- },
- "jest-runtime": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.3.1.tgz",
- "integrity": "sha512-jLzkIxIqXwBEOZx7wx9OO9sxoZmgT2NhmQKzHQm1xwR1kNW/dn0OjxR424VwHHf1SPN6Qwlb5pp1oGCeFTQ62A==",
- "dev": true,
- "requires": {
- "@jest/environment": "^29.3.1",
- "@jest/fake-timers": "^29.3.1",
- "@jest/globals": "^29.3.1",
- "@jest/source-map": "^29.2.0",
- "@jest/test-result": "^29.3.1",
- "@jest/transform": "^29.3.1",
- "@jest/types": "^29.3.1",
- "@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.3.1",
- "jest-message-util": "^29.3.1",
- "jest-mock": "^29.3.1",
- "jest-regex-util": "^29.2.0",
- "jest-resolve": "^29.3.1",
- "jest-snapshot": "^29.3.1",
- "jest-util": "^29.3.1",
- "slash": "^3.0.0",
- "strip-bom": "^4.0.0"
- }
- },
- "jest-snapshot": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.3.1.tgz",
- "integrity": "sha512-+3JOc+s28upYLI2OJM4PWRGK9AgpsMs/ekNryUV0yMBClT9B1DF2u2qay8YxcQd338PPYSFNb0lsar1B49sLDA==",
- "dev": true,
- "requires": {
- "@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/traverse": "^7.7.2",
- "@babel/types": "^7.3.3",
- "@jest/expect-utils": "^29.3.1",
- "@jest/transform": "^29.3.1",
- "@jest/types": "^29.3.1",
- "@types/babel__traverse": "^7.0.6",
- "@types/prettier": "^2.1.5",
- "babel-preset-current-node-syntax": "^1.0.0",
- "chalk": "^4.0.0",
- "expect": "^29.3.1",
- "graceful-fs": "^4.2.9",
- "jest-diff": "^29.3.1",
- "jest-get-type": "^29.2.0",
- "jest-haste-map": "^29.3.1",
- "jest-matcher-utils": "^29.3.1",
- "jest-message-util": "^29.3.1",
- "jest-util": "^29.3.1",
- "natural-compare": "^1.4.0",
- "pretty-format": "^29.3.1",
- "semver": "^7.3.5"
- },
- "dependencies": {
- "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
- },
- "diff-sequences": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.3.1.tgz",
- "integrity": "sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==",
- "dev": true
- },
- "jest-diff": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.3.1.tgz",
- "integrity": "sha512-vU8vyiO7568tmin2lA3r2DP8oRvzhvRcD4DjpXc6uGveQodyk7CKLhQlCSiwgx3g0pFaE88/KLZ0yaTWMc4Uiw==",
- "dev": true,
- "requires": {
- "chalk": "^4.0.0",
- "diff-sequences": "^29.3.1",
- "jest-get-type": "^29.2.0",
- "pretty-format": "^29.3.1"
- }
- },
- "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,
- "requires": {
- "yallist": "^4.0.0"
- }
- },
- "pretty-format": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz",
- "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==",
- "dev": true,
- "requires": {
- "@jest/schemas": "^29.0.0",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- }
- },
- "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
- },
- "semver": {
- "version": "7.3.8",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
- "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
- "dev": true,
- "requires": {
- "lru-cache": "^6.0.0"
- }
- },
- "yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "dev": true
- }
- }
- },
- "jest-util": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.3.1.tgz",
- "integrity": "sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ==",
- "dev": true,
- "requires": {
- "@jest/types": "^29.3.1",
- "@types/node": "*",
- "chalk": "^4.0.0",
- "ci-info": "^3.2.0",
- "graceful-fs": "^4.2.9",
- "picomatch": "^2.2.3"
- }
- },
- "jest-validate": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.3.1.tgz",
- "integrity": "sha512-N9Lr3oYR2Mpzuelp1F8negJR3YE+L1ebk1rYA5qYo9TTY3f9OWdptLoNSPP9itOCBIRBqjt/S5XHlzYglLN67g==",
- "dev": true,
- "requires": {
- "@jest/types": "^29.3.1",
- "camelcase": "^6.2.0",
- "chalk": "^4.0.0",
- "jest-get-type": "^29.2.0",
- "leven": "^3.1.0",
- "pretty-format": "^29.3.1"
- },
- "dependencies": {
- "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
- },
- "camelcase": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
- "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
- "dev": true
- },
- "pretty-format": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.3.1.tgz",
- "integrity": "sha512-FyLnmb1cYJV8biEIiRyzRFvs2lry7PPIvOqKVe1GCUEYg4YGmlx1qG9EJNMxArYm7piII4qb8UV1Pncq5dxmcg==",
- "dev": true,
- "requires": {
- "@jest/schemas": "^29.0.0",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- }
- },
- "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
- }
- }
- },
- "jest-watcher": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.3.1.tgz",
- "integrity": "sha512-RspXG2BQFDsZSRKGCT/NiNa8RkQ1iKAjrO0//soTMWx/QUt+OcxMqMSBxz23PYGqUuWm2+m2mNNsmj0eIoOaFg==",
- "dev": true,
- "requires": {
- "@jest/test-result": "^29.3.1",
- "@jest/types": "^29.3.1",
- "@types/node": "*",
- "ansi-escapes": "^4.2.1",
- "chalk": "^4.0.0",
- "emittery": "^0.13.1",
- "jest-util": "^29.3.1",
- "string-length": "^4.0.1"
- }
- },
- "jest-worker": {
- "version": "29.3.1",
- "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.3.1.tgz",
- "integrity": "sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw==",
- "dev": true,
- "requires": {
- "@types/node": "*",
- "jest-util": "^29.3.1",
- "merge-stream": "^2.0.0",
- "supports-color": "^8.0.0"
- },
- "dependencies": {
- "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,
- "requires": {
- "has-flag": "^4.0.0"
- }
- }
- }
- },
- "js-sdsl": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz",
- "integrity": "sha512-FfVSdx6pJ41Oa+CF7RDaFmTnCaFhua+SNYQX74riGOpl96x+2jQCqEfQ2bnXu/5DPCqlRuiqyvTJM0Qjz26IVg==",
- "dev": true
- },
- "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
- },
- "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,
- "requires": {
- "argparse": "^1.0.7",
- "esprima": "^4.0.0"
- }
- },
- "jsesc": {
- "version": "2.5.2",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
- "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
- "dev": true
- },
- "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
- },
- "json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true
- },
- "json-stable-stringify-without-jsonify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
- "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
- "dev": true
- },
- "json5": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
- "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
- "dev": true
- },
- "kleur": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
- "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
- "dev": true
- },
- "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
- },
- "levn": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
- "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
- "dev": true,
- "requires": {
- "prelude-ls": "^1.2.1",
- "type-check": "~0.4.0"
- }
- },
- "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
- },
- "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,
- "requires": {
- "p-locate": "^4.1.0"
- }
- },
- "lodash.memoize": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
- "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==",
- "dev": true
- },
- "lodash.merge": {
- "version": "4.6.2",
- "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
- "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
- "dev": true
- },
- "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,
- "requires": {
- "yallist": "^3.0.2"
- }
- },
- "make-dir": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
- "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
- "dev": true,
- "requires": {
- "semver": "^6.0.0"
- }
- },
- "make-error": {
- "version": "1.3.6",
- "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
- "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
- "dev": true
- },
- "makeerror": {
- "version": "1.0.12",
- "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
- "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
- "dev": true,
- "requires": {
- "tmpl": "1.0.5"
- }
- },
- "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
- },
- "merge2": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
- "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
- "dev": true
- },
- "micromatch": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
- "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
- "dev": true,
- "requires": {
- "braces": "^3.0.2",
- "picomatch": "^2.3.1"
- }
- },
- "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
- },
- "minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "dev": true,
- "requires": {
- "brace-expansion": "^1.1.7"
- }
- },
- "minimist": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
- "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
- "dev": true
- },
- "mkdirp": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
- "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
- "dev": true
- },
- "mnemonist": {
- "version": "0.38.3",
- "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.3.tgz",
- "integrity": "sha512-2K9QYubXx/NAjv4VLq1d1Ly8pWNC5L3BrixtdkyTegXWJIqY+zLNDhhX/A+ZwWt70tB1S8H4BE8FLYEFyNoOBw==",
- "requires": {
- "obliterator": "^1.6.1"
- }
- },
- "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
- },
- "natural-compare": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
- "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
- "dev": true
- },
- "natural-compare-lite": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
- "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
- "dev": true
- },
- "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-releases": {
- "version": "2.0.8",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz",
- "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==",
- "dev": true
- },
- "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
- },
- "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,
- "requires": {
- "path-key": "^3.0.0"
- }
- },
- "object-inspect": {
- "version": "1.12.3",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
- "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==",
- "dev": true
- },
- "object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true
- },
- "object.assign": {
- "version": "4.1.4",
- "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
- "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
- "has-symbols": "^1.0.3",
- "object-keys": "^1.1.1"
- }
- },
- "object.values": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz",
- "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
- "es-abstract": "^1.20.4"
- }
- },
- "obliterator": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-1.6.1.tgz",
- "integrity": "sha512-9WXswnqINnnhOG/5SLimUlzuU1hFJUc8zkwyD59Sd+dPOMf05PmnYG/d6Q7HZ+KmgkZJa1PxRso6QdM3sTNHig=="
- },
- "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,
- "requires": {
- "wrappy": "1"
- }
- },
- "onetime": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
- "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
- "dev": true,
- "requires": {
- "mimic-fn": "^2.1.0"
- }
- },
- "optionator": {
- "version": "0.9.1",
- "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
- "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
- "dev": true,
- "requires": {
- "deep-is": "^0.1.3",
- "fast-levenshtein": "^2.0.6",
- "levn": "^0.4.1",
- "prelude-ls": "^1.2.1",
- "type-check": "^0.4.0",
- "word-wrap": "^1.2.3"
- }
- },
- "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,
- "requires": {
- "yocto-queue": "^0.1.0"
- }
- },
- "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,
- "requires": {
- "p-limit": "^2.2.0"
- },
- "dependencies": {
- "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,
- "requires": {
- "p-try": "^2.0.0"
- }
- }
- }
- },
- "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
- },
- "parent-module": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
- "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
- "dev": true,
- "requires": {
- "callsites": "^3.0.0"
- }
- },
- "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,
- "requires": {
- "@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"
- }
- },
- "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
- },
- "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
- },
- "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
- },
- "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
- },
- "path-type": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
- "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
- "dev": true
- },
- "picocolors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
- "dev": true
- },
- "picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true
- },
- "pirates": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz",
- "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==",
- "dev": true
- },
- "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,
- "requires": {
- "find-up": "^4.0.0"
- }
- },
- "prelude-ls": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
- "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
- "dev": true
- },
- "prettier": {
- "version": "2.8.7",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.7.tgz",
- "integrity": "sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==",
- "dev": true,
- "peer": true
- },
- "prettier-linter-helpers": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
- "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
- "dev": true,
- "requires": {
- "fast-diff": "^1.1.2"
- }
- },
- "pretty-format": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz",
- "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==",
- "dev": true,
- "requires": {
- "@jest/types": "^26.6.2",
- "ansi-regex": "^5.0.0",
- "ansi-styles": "^4.0.0",
- "react-is": "^17.0.1"
- },
- "dependencies": {
- "@jest/types": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz",
- "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==",
- "dev": true,
- "requires": {
- "@types/istanbul-lib-coverage": "^2.0.0",
- "@types/istanbul-reports": "^3.0.0",
- "@types/node": "*",
- "@types/yargs": "^15.0.0",
- "chalk": "^4.0.0"
- }
- },
- "@types/yargs": {
- "version": "15.0.15",
- "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.15.tgz",
- "integrity": "sha512-IziEYMU9XoVj8hWg7k+UJrXALkGFjWJhn5QFEv9q4p+v40oZhSuC135M38st8XPjICL7Ey4TV64ferBGUoJhBg==",
- "dev": true,
- "requires": {
- "@types/yargs-parser": "*"
- }
- }
- }
- },
- "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,
- "requires": {
- "kleur": "^3.0.3",
- "sisteransi": "^1.0.5"
- }
- },
- "punycode": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
- "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
- "dev": true
- },
- "queue-microtask": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
- "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
- "dev": true
- },
- "react-is": {
- "version": "17.0.2",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
- "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
- "dev": true
- },
- "regexp.prototype.flags": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
- "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.3",
- "functions-have-names": "^1.2.2"
- }
- },
- "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
- },
- "resolve": {
- "version": "1.22.1",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
- "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
- "dev": true,
- "requires": {
- "is-core-module": "^2.9.0",
- "path-parse": "^1.0.7",
- "supports-preserve-symlinks-flag": "^1.0.0"
- }
- },
- "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,
- "requires": {
- "resolve-from": "^5.0.0"
- }
- },
- "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
- },
- "resolve.exports": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz",
- "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==",
- "dev": true
- },
- "reusify": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
- "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
- "dev": true
- },
- "rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "dev": true,
- "requires": {
- "glob": "^7.1.3"
- }
- },
- "run-parallel": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
- "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
- "dev": true,
- "requires": {
- "queue-microtask": "^1.2.2"
- }
- },
- "safe-regex-test": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz",
- "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.1.3",
- "is-regex": "^1.1.4"
- }
- },
- "semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
- "dev": true
- },
- "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,
- "requires": {
- "shebang-regex": "^3.0.0"
- }
- },
- "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
- },
- "side-channel": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
- "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.0",
- "get-intrinsic": "^1.0.2",
- "object-inspect": "^1.9.0"
- }
- },
- "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
- },
- "sisteransi": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
- "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
- "dev": true
- },
- "slash": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
- "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
- "dev": true
- },
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
- },
- "source-map-support": {
- "version": "0.5.21",
- "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
- "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
- "requires": {
- "buffer-from": "^1.0.0",
- "source-map": "^0.6.0"
- }
- },
- "sprintf-js": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
- "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
- "dev": true
- },
- "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,
- "requires": {
- "escape-string-regexp": "^2.0.0"
- }
- },
- "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,
- "requires": {
- "char-regex": "^1.0.2",
- "strip-ansi": "^6.0.0"
- }
- },
- "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,
- "requires": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- }
- },
- "string.prototype.trim": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz",
- "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
- "es-abstract": "^1.20.4"
- }
- },
- "string.prototype.trimend": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz",
- "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
- "es-abstract": "^1.20.4"
- }
- },
- "string.prototype.trimstart": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz",
- "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
- "es-abstract": "^1.20.4"
- }
- },
- "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,
- "requires": {
- "ansi-regex": "^5.0.1"
- }
- },
- "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
- },
- "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
- },
- "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
- },
- "strnum": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
- "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA=="
- },
- "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,
- "requires": {
- "has-flag": "^4.0.0"
- }
- },
- "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
- },
- "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,
- "requires": {
- "@istanbuljs/schema": "^0.1.2",
- "glob": "^7.1.4",
- "minimatch": "^3.0.4"
- }
- },
- "text-table": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
- "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
- "dev": true
- },
- "tmpl": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
- "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
- "dev": true
- },
- "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
- },
- "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,
- "requires": {
- "is-number": "^7.0.0"
- }
- },
- "ts-jest": {
- "version": "29.0.3",
- "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.3.tgz",
- "integrity": "sha512-Ibygvmuyq1qp/z3yTh9QTwVVAbFdDy/+4BtIQR2sp6baF2SJU/8CKK/hhnGIDY2L90Az2jIqTwZPnN2p+BweiQ==",
- "dev": true,
- "requires": {
- "bs-logger": "0.x",
- "fast-json-stable-stringify": "2.x",
- "jest-util": "^29.0.0",
- "json5": "^2.2.1",
- "lodash.memoize": "4.x",
- "make-error": "1.x",
- "semver": "7.x",
- "yargs-parser": "^21.0.1"
- },
- "dependencies": {
- "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,
- "requires": {
- "yallist": "^4.0.0"
- }
- },
- "semver": {
- "version": "7.3.8",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
- "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
- "dev": true,
- "requires": {
- "lru-cache": "^6.0.0"
- }
- },
- "yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "dev": true
- }
- }
- },
- "ts-node": {
- "version": "10.9.1",
- "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz",
- "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==",
- "dev": true,
- "requires": {
- "@cspotcode/source-map-support": "^0.8.0",
- "@tsconfig/node10": "^1.0.7",
- "@tsconfig/node12": "^1.0.7",
- "@tsconfig/node14": "^1.0.0",
- "@tsconfig/node16": "^1.0.2",
- "acorn": "^8.4.1",
- "acorn-walk": "^8.1.1",
- "arg": "^4.1.0",
- "create-require": "^1.1.0",
- "diff": "^4.0.1",
- "make-error": "^1.1.1",
- "v8-compile-cache-lib": "^3.0.1",
- "yn": "3.1.1"
- },
- "dependencies": {
- "diff": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
- "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
- "dev": true
- }
- }
- },
- "tsconfig-paths": {
- "version": "3.14.2",
- "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz",
- "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==",
- "dev": true,
- "requires": {
- "@types/json5": "^0.0.29",
- "json5": "^1.0.2",
- "minimist": "^1.2.6",
- "strip-bom": "^3.0.0"
- },
- "dependencies": {
- "json5": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
- "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
- "dev": true,
- "requires": {
- "minimist": "^1.2.0"
- }
- },
- "strip-bom": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
- "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
- "dev": true
- }
- }
- },
- "tslib": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
- "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
- },
- "tsutils": {
- "version": "3.21.0",
- "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
- "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
- "dev": true,
- "requires": {
- "tslib": "^1.8.1"
- },
- "dependencies": {
- "tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
- "dev": true
- }
- }
- },
- "type-check": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
- "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
- "dev": true,
- "requires": {
- "prelude-ls": "^1.2.1"
- }
- },
- "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
- },
- "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
- },
- "typed-array-length": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
- "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "for-each": "^0.3.3",
- "is-typed-array": "^1.1.9"
- }
- },
- "typescript": {
- "version": "4.9.4",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz",
- "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==",
- "dev": true
- },
- "unbox-primitive": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
- "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
- "dev": true,
- "requires": {
- "call-bind": "^1.0.2",
- "has-bigints": "^1.0.2",
- "has-symbols": "^1.0.3",
- "which-boxed-primitive": "^1.0.2"
- }
- },
- "update-browserslist-db": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
- "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==",
- "dev": true,
- "requires": {
- "escalade": "^3.1.1",
- "picocolors": "^1.0.0"
- }
- },
- "uri-js": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
- "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
- "dev": true,
- "requires": {
- "punycode": "^2.1.0"
- }
- },
- "uuid": {
- "version": "8.3.2",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
- "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
- },
- "v8-compile-cache-lib": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
- "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
- "dev": true
- },
- "v8-to-istanbul": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz",
- "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==",
- "dev": true,
- "requires": {
- "@jridgewell/trace-mapping": "^0.3.12",
- "@types/istanbul-lib-coverage": "^2.0.1",
- "convert-source-map": "^1.6.0"
- },
- "dependencies": {
- "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
- }
- }
- },
- "walker": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
- "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
- "dev": true,
- "requires": {
- "makeerror": "1.0.12"
- }
- },
- "which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
- "requires": {
- "isexe": "^2.0.0"
- }
- },
- "which-boxed-primitive": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
- "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
- "dev": true,
- "requires": {
- "is-bigint": "^1.0.1",
- "is-boolean-object": "^1.1.0",
- "is-number-object": "^1.0.4",
- "is-string": "^1.0.5",
- "is-symbol": "^1.0.3"
- }
- },
- "which-typed-array": {
- "version": "1.1.9",
- "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz",
- "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==",
- "dev": true,
- "requires": {
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.2",
- "for-each": "^0.3.3",
- "gopd": "^1.0.1",
- "has-tostringtag": "^1.0.0",
- "is-typed-array": "^1.1.10"
- }
- },
- "word-wrap": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
- "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
- "dev": true
- },
- "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,
- "requires": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- }
- },
- "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
- },
- "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,
- "requires": {
- "imurmurhash": "^0.1.4",
- "signal-exit": "^3.0.7"
- }
- },
- "xml": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz",
- "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==",
- "dev": true
- },
- "y18n": {
- "version": "5.0.8",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
- "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
- "dev": true
- },
- "yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
- "dev": true
- },
- "yargs": {
- "version": "17.6.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz",
- "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==",
- "dev": true,
- "requires": {
- "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"
- }
- },
- "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
- },
- "yn": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
- "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
- "dev": true
- },
- "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
- }
- }
-}
diff --git a/source/infrastructure/package.json b/source/infrastructure/package.json
deleted file mode 100644
index b2a8391b..00000000
--- a/source/infrastructure/package.json
+++ /dev/null
@@ -1,45 +0,0 @@
-{
- "name": "aws-instance-scheduler",
- "version": "1.5.0",
- "bin": {
- "aws-instance-scheduler": "infrastructure/bin/aws-instance-scheduler.js"
- },
- "scripts": {
- "cleanup": "tsc --build ./ --clean && rm -rf node_modules && rm -f package-lock.json",
- "build": "tsc",
- "watch": "tsc -w",
- "synth": "cd instance-scheduler && cdk synth",
- "test": "jest --config instance-scheduler/jest.config.ts",
- "e2e-tests": "jest --config pipeline/jest.config.ts",
- "cdk": "cdk"
- },
- "devDependencies": {
- "@types/jest": "^26.0.10",
- "@types/node": "10.17.27",
- "@typescript-eslint/eslint-plugin": "^5.55.0",
- "aws-cdk": "^2.68.0",
- "eslint": "^8.36.0",
- "eslint-config-prettier": "^8.7.0",
- "eslint-plugin-header": "^3.1.1",
- "eslint-plugin-import": "^2.27.5",
- "eslint-plugin-prettier": "^4.2.1",
- "jest": "^29.3.1",
- "jest-extended": "^3.2.4",
- "jest-junit": "^15.0.0",
- "ts-jest": "^29.0.3",
- "ts-node": "^10.9.1",
- "typescript": "^4.9.4"
- },
- "dependencies": {
- "@aws-cdk/aws-servicecatalogappregistry-alpha": "^2.62.2-alpha.0",
- "@aws-cdk/aws-lambda-python-alpha": "~2.68.0-alpha.0",
- "@aws-solutions-constructs/aws-lambda-dynamodb": "2.30.0",
- "aws-cdk-lib": "^2.62.0",
- "cdk-nag": "^2.22.23",
- "constructs": "^10.0.0",
- "source-map-support": "^0.5.16",
- "@aws-sdk/client-ec2": "^3.295.0",
- "@aws-sdk/client-dynamodb": "^3.295.0",
- "@aws-sdk/client-rds" : "^3.314.0"
- }
-}
diff --git a/source/infrastructure/pipeline/bin/testing-pipeline.ts b/source/infrastructure/pipeline/bin/testing-pipeline.ts
deleted file mode 100644
index 9a0f624f..00000000
--- a/source/infrastructure/pipeline/bin/testing-pipeline.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/env node
-// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-// SPDX-License-Identifier: Apache-2.0
-
-import * as cdk from "aws-cdk-lib";
-import { Aspects } from "aws-cdk-lib";
-import { AwsSolutionsChecks } from "cdk-nag";
-import { E2eTestStack } from "../lib/e2e-test-stack";
-import PipelineStack from "../lib/pipeline-stack";
-
-const app = new cdk.App();
-
-new PipelineStack(app, "aws-instance-scheduler-testing-pipeline");
-
-/*
-E2eTestStack does not actually need to be built here to work in the pipeline,
-but building it here ensures it gets covered by CDK-Nag
- */
-new E2eTestStack(app, "aws-instance-scheduler-end-to-end-testing-resources");
-
-Aspects.of(app).add(
- new AwsSolutionsChecks({
- verbose: true,
- })
-);
diff --git a/source/infrastructure/pipeline/cdk.json b/source/infrastructure/pipeline/cdk.json
deleted file mode 100644
index 10ce85f0..00000000
--- a/source/infrastructure/pipeline/cdk.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "app": "npx ts-node bin/testing-pipeline.ts",
- "output": "../../../build/cdk.pipeline.out"
-}
diff --git a/source/infrastructure/tsconfig.json b/source/infrastructure/tsconfig.json
deleted file mode 100644
index 0d7f185c..00000000
--- a/source/infrastructure/tsconfig.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "compilerOptions": {
- "alwaysStrict": true,
- "charset": "utf8",
- "declaration": true,
- "experimentalDecorators": false,
- "inlineSourceMap": true,
- "inlineSources": true,
- "lib": ["es2021", "dom"],
- "module": "CommonJS",
- "noEmitOnError": true,
- "noFallthroughCasesInSwitch": true,
- "noImplicitAny": true,
- "noImplicitReturns": true,
- "noImplicitThis": true,
- "noUnusedLocals": true,
- "noUnusedParameters": true,
- "resolveJsonModule": true,
- "strict": true,
- "strictNullChecks": true,
- "strictPropertyInitialization": true,
- "stripInternal": true,
- "target": "ES2022",
- "allowJs": false,
- "outDir": "../../build/cdk.ts.dist"
- },
- "include": ["**/*.ts"],
- "files" : ["global.d.ts"],
- "exclude": ["node_modules"]
-}
diff --git a/source/instance-scheduler.ts b/source/instance-scheduler.ts
new file mode 100644
index 00000000..08363c01
--- /dev/null
+++ b/source/instance-scheduler.ts
@@ -0,0 +1,106 @@
+#!/usr/bin/env node
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+import { App, Aspects, DefaultStackSynthesizer, StackSynthesizer } from "aws-cdk-lib";
+import { AwsSolutionsChecks, NagSuppressions } from "cdk-nag";
+import { getSolutionContext } from "./instance-scheduler/lib/cdk-context";
+import { InstanceSchedulerStack } from "./instance-scheduler/lib/instance-scheduler-stack";
+import { InstanceSchedulerRemoteStack } from "./instance-scheduler/lib/remote-stack";
+import { SourceProvider, TestingPipelineStack } from "./pipeline/lib/testing-pipeline-stack";
+import { E2eTestStack } from "./pipeline/lib/e2e-test-stack";
+import { PipelineBootstrapStack } from "./pipeline/lib/pipeline-bootstrap-stack";
+import { buildCodeCommitSource } from "./pipeline/lib/code-commit-source";
+import { buildCodeStarSource } from "./pipeline/lib/code-star-source";
+
+interface AppProps {
+ solutionVersion: string;
+ synthesizer: StackSynthesizer;
+}
+
+function addAppStacks(app: App, props: AppProps): void {
+ const solutionDetails = getSolutionContext(app);
+
+ const hubStack = new InstanceSchedulerStack(app, "instance-scheduler-on-aws", {
+ synthesizer: props.synthesizer,
+ description: `(${solutionDetails.solutionId}) ${solutionDetails.solutionName} ${props.solutionVersion}`,
+ solutionId: solutionDetails.solutionId,
+ solutionName: solutionDetails.solutionName,
+ solutionVersion: props.solutionVersion,
+ appregApplicationName: solutionDetails.appRegAppName,
+ appregSolutionName: solutionDetails.appRegSolutionName,
+ });
+
+ new InstanceSchedulerRemoteStack(app, "instance-scheduler-on-aws-remote", {
+ synthesizer: props.synthesizer,
+ description: `(${solutionDetails.solutionId}S) ${solutionDetails.solutionName} remote ${props.solutionVersion}`,
+ solutionId: solutionDetails.solutionId,
+ solutionName: solutionDetails.solutionName,
+ solutionVersion: props.solutionVersion,
+ appregApplicationName: solutionDetails.appRegAppName,
+ appregSolutionName: solutionDetails.appRegSolutionName,
+ });
+
+ NagSuppressions.addResourceSuppressionsByPath(
+ hubStack,
+ "/instance-scheduler-on-aws/SchedulerRole/DefaultPolicy/Resource",
+ [
+ {
+ id: "AwsSolutions-IAM5",
+ reason: "The scheduling lambda must access multiple resources across services",
+ },
+ ],
+ );
+}
+
+function getSourceProvider(sourceType: string): SourceProvider {
+ switch (sourceType) {
+ case "codecommit":
+ return { getSource: buildCodeCommitSource };
+ case "codestar":
+ return { getSource: buildCodeStarSource };
+ default:
+ throw Error("Unknown source type");
+ }
+}
+
+function addPipelineStacks(app: App): void {
+ new PipelineBootstrapStack(app, "instance-scheduler-on-aws-testing-pipeline-bootstrap");
+ const sourceType = app.node.tryGetContext("instance-scheduler-on-aws-pipeline-source") ?? "codecommit";
+ new TestingPipelineStack(app, "instance-scheduler-on-aws-testing-pipeline", getSourceProvider(sourceType));
+
+ /*
+ E2eTestStack does not actually need to be built here to work in the pipeline,
+ but building it here ensures it gets covered by CDK-Nag
+ */
+ new E2eTestStack(app, "instance-scheduler-on-aws-end-to-end-testing-resources");
+}
+
+function main(): void {
+ const packageVersion =
+ process.env.npm_package_version ??
+ (() => {
+ throw new Error("npm package version not available, invoke synth from npm");
+ })();
+ let solutionVersion = `v${packageVersion}`;
+ let synthesizer = new DefaultStackSynthesizer();
+
+ const { DIST_OUTPUT_BUCKET, SOLUTION_NAME, VERSION } = process.env;
+ const solutionsPipelineOverrides = DIST_OUTPUT_BUCKET && SOLUTION_NAME && VERSION;
+
+ if (solutionsPipelineOverrides) {
+ solutionVersion = VERSION;
+ synthesizer = new DefaultStackSynthesizer({
+ generateBootstrapVersionRule: false,
+ fileAssetsBucketName: `${DIST_OUTPUT_BUCKET}-\${AWS::Region}`,
+ bucketPrefix: `${SOLUTION_NAME}/${VERSION}/`,
+ });
+ }
+
+ const app = new App();
+ Aspects.of(app).add(new AwsSolutionsChecks({ verbose: true }));
+
+ addAppStacks(app, { solutionVersion, synthesizer });
+ addPipelineStacks(app);
+}
+
+main();
diff --git a/source/infrastructure/instance-scheduler/lib/app-registry.ts b/source/instance-scheduler/lib/app-registry.ts
similarity index 88%
rename from source/infrastructure/instance-scheduler/lib/app-registry.ts
rename to source/instance-scheduler/lib/app-registry.ts
index 07798dff..f166b7b9 100644
--- a/source/infrastructure/instance-scheduler/lib/app-registry.ts
+++ b/source/instance-scheduler/lib/app-registry.ts
@@ -33,17 +33,17 @@ export class AppRegistryForInstanceScheduler extends Construct {
]),
description: `Service Catalog application to track and manage all your resources for the solution ${map.findInMap(
"Data",
- "SolutionName"
+ "SolutionName",
)}`,
});
- application.associateStack(scope);
+ application.associateApplicationWithStack(scope);
Tags.of(application).add("Solutions:SolutionID", map.findInMap("Data", "ID"));
Tags.of(application).add("Solutions:SolutionName", map.findInMap("Data", "SolutionName"));
Tags.of(application).add("Solutions:SolutionVersion", map.findInMap("Data", "Version"));
Tags.of(application).add("Solutions:ApplicationType", map.findInMap("Data", "ApplicationType"));
- const attributeGroup = new appreg.AttributeGroup(this, "DefaultApplicationAttributes", {
- attributeGroupName: cdk.Fn.join("-", [Aws.REGION, Aws.STACK_NAME]),
+ application.addAttributeGroup("DefaultApplicationAttributes", {
+ attributeGroupName: `attgroup-${cdk.Fn.join("-", [Aws.REGION, Aws.STACK_NAME])}`,
description: "Attribute group for solution information",
attributes: {
applicationType: map.findInMap("Data", "ApplicationType"),
@@ -52,7 +52,5 @@ export class AppRegistryForInstanceScheduler extends Construct {
solutionName: map.findInMap("Data", "SolutionName"),
},
});
-
- application.associateAttributeGroup(attributeGroup);
}
}
diff --git a/source/infrastructure/instance-scheduler/bin/cdk-context.ts b/source/instance-scheduler/lib/cdk-context.ts
similarity index 87%
rename from source/infrastructure/instance-scheduler/bin/cdk-context.ts
rename to source/instance-scheduler/lib/cdk-context.ts
index 708bc0bd..7d7136bb 100644
--- a/source/infrastructure/instance-scheduler/bin/cdk-context.ts
+++ b/source/instance-scheduler/lib/cdk-context.ts
@@ -5,7 +5,6 @@ import { App } from "aws-cdk-lib";
export function getSolutionContext(app: App) {
return {
solutionId: app.node.tryGetContext("solutionId"),
- solutionVersion: app.node.tryGetContext("solutionVersion"),
solutionName: app.node.tryGetContext("solutionName"),
appRegAppName: app.node.tryGetContext("appRegApplicationName"),
appRegSolutionName: app.node.tryGetContext("appRegSolutionName"),
diff --git a/source/infrastructure/instance-scheduler/lib/core-scheduler.ts b/source/instance-scheduler/lib/core-scheduler.ts
similarity index 94%
rename from source/infrastructure/instance-scheduler/lib/core-scheduler.ts
rename to source/instance-scheduler/lib/core-scheduler.ts
index bce01a25..fe53352c 100644
--- a/source/infrastructure/instance-scheduler/lib/core-scheduler.ts
+++ b/source/instance-scheduler/lib/core-scheduler.ts
@@ -32,15 +32,18 @@ export class CoreScheduler {
this.lambdaFunction = new python.PythonFunction(scope, "scheduler-lambda", {
functionName: Aws.STACK_NAME + "-InstanceSchedulerMain",
description: "EC2 and RDS instance scheduler, version " + props.solutionVersion,
- entry: `${__dirname}/../../../app`,
+ entry: `${__dirname}/../../app`,
index: "instance_scheduler/main.py",
handler: "lambda_handler",
- runtime: lambda.Runtime.PYTHON_3_9,
+ runtime: lambda.Runtime.PYTHON_3_10,
role: props.schedulerRole,
memorySize: props.memorySize,
timeout: cdk.Duration.seconds(300),
environment: props.environment,
tracing: lambda.Tracing.ACTIVE,
+ bundling: {
+ assetExcludes: [".mypy_cache", ".tox", "__pycache__"],
+ },
});
const lambdaToDynamoDbConstruct = new LambdaToDynamoDB(scope, "instance-scheduler-lambda", {
@@ -66,7 +69,7 @@ export class CoreScheduler {
const cfnStateTable = this.stateTable.node.defaultChild as dynamodb.CfnTable;
cfnStateTable.overrideLogicalId("StateTable");
cfnStateTable.addPropertyOverride("SSESpecification", {
- KMSMasterKeyId: { Ref: "InstanceSchedulerEncryptionKey" },
+ KMSMasterKeyId: props.kmsEncryptionKey.keyId,
SSEEnabled: true,
SSEType: "KMS",
});
@@ -110,7 +113,7 @@ export class CoreScheduler {
const cfnMaintenanceWindowTable = this.maintenanceWindowTable.node.defaultChild as dynamodb.CfnTable;
cfnMaintenanceWindowTable.overrideLogicalId("MaintenanceWindowTable");
cfnMaintenanceWindowTable.addPropertyOverride("SSESpecification", {
- KMSMasterKeyId: { Ref: "InstanceSchedulerEncryptionKey" },
+ KMSMasterKeyId: props.kmsEncryptionKey.keyId,
SSEEnabled: true,
SSEType: "KMS",
});
diff --git a/source/infrastructure/instance-scheduler/lib/event-bus-resources.ts b/source/instance-scheduler/lib/event-bus-resources.ts
similarity index 100%
rename from source/infrastructure/instance-scheduler/lib/event-bus-resources.ts
rename to source/instance-scheduler/lib/event-bus-resources.ts
diff --git a/source/infrastructure/instance-scheduler/lib/aws-instance-scheduler-stack.ts b/source/instance-scheduler/lib/instance-scheduler-stack.ts
similarity index 84%
rename from source/infrastructure/instance-scheduler/lib/aws-instance-scheduler-stack.ts
rename to source/instance-scheduler/lib/instance-scheduler-stack.ts
index 4d65fbc4..3a68b3a3 100644
--- a/source/infrastructure/instance-scheduler/lib/aws-instance-scheduler-stack.ts
+++ b/source/instance-scheduler/lib/instance-scheduler-stack.ts
@@ -12,7 +12,7 @@ import * as lambda from "aws-cdk-lib/aws-lambda";
import * as sns from "aws-cdk-lib/aws-sns";
import * as events from "aws-cdk-lib/aws-events";
import { Construct } from "constructs";
-import { LambdaFunction } from "aws-cdk-lib/aws-events-targets";
+import * as EBEventTarget from "aws-cdk-lib/aws-events-targets";
import * as dynamodb from "aws-cdk-lib/aws-dynamodb";
import { SUPPORTED_TIME_ZONES } from "./time-zones";
import { AppRegistryForInstanceScheduler } from "./app-registry";
@@ -20,7 +20,7 @@ import { NagSuppressions } from "cdk-nag";
import { CoreScheduler } from "./core-scheduler";
import { SchedulerEventBusResources, SchedulerEventBusProps } from "./event-bus-resources";
-export interface AwsInstanceSchedulerStackProps extends cdk.StackProps {
+export interface InstanceSchedulerStackProps extends cdk.StackProps {
readonly description: string;
readonly solutionId: string;
readonly solutionName: string;
@@ -28,10 +28,11 @@ export interface AwsInstanceSchedulerStackProps extends cdk.StackProps {
readonly appregApplicationName: string;
readonly appregSolutionName: string;
- readonly paramOverrides?: AwsInstanceSchedulerParameterDefaultOverrides;
+ readonly paramOverrides?: InstanceSchedulerParameterDefaultOverrides;
+ readonly disableOpMetrics?: boolean;
}
-export interface AwsInstanceSchedulerParameterDefaultOverrides {
+export interface InstanceSchedulerParameterDefaultOverrides {
readonly schedulingActive?: "Yes" | "No";
readonly scheduledServices?: "EC2" | "RDS" | "Both";
readonly scheduleRdsClusters?: "Yes" | "No";
@@ -70,19 +71,19 @@ export interface AwsInstanceSchedulerParameterDefaultOverrides {
}
/*
- * AWS instance scheduler stack, utilizes two cdk constructs, aws-lambda-dynamodb and aws-events-rule-lambda.
+ * Instance Scheduler on AWS stack
* The stack has three dynamoDB tables defined for storing the state, configuration and maintenance information.
* The stack also includes one lambda, which is scheduled using an AWS CloudWatch Event Rule.
* The stack also includes a cloudwatch log group for the entire solution, encryption key, encryption key alias and SNS topic,
* and the necessary AWS IAM Policies and IAM Roles. For more information on the architecture, refer to the documentation at
- * https://aws.amazon.com/solutions/implementations/instance-scheduler/?did=sl_card&trk=sl_card
+ * https://aws.amazon.com/solutions/implementations/instance-scheduler-on-aws/
*/
-export class AwsInstanceSchedulerStack extends cdk.Stack {
+export class InstanceSchedulerStack extends cdk.Stack {
readonly configurationTableOutput: CfnOutput;
readonly issueSnsTopicArn: CfnOutput;
readonly schedulerRoleArn: CfnOutput;
- constructor(scope: Construct, id: string, props: AwsInstanceSchedulerStackProps) {
+ constructor(scope: Construct, id: string, props: InstanceSchedulerStackProps) {
super(scope, id, props);
//Start CFN Parameters for instance scheduler.
@@ -187,13 +188,13 @@ export class AwsInstanceSchedulerStack extends cdk.Stack {
const regions = new cdk.CfnParameter(this, "Regions", {
type: "CommaDelimitedList",
- description: "List of regions in which instances are scheduled, leave blank for current region only.",
+ description: "List of regions in which instances should be scheduled, leave blank for current region only.",
default: props.paramOverrides?.regions ?? "",
});
const usingAWSOrganizations = new cdk.CfnParameter(this, "UsingAWSOrganizations", {
type: "String",
- description: "Is the hub account member of the AWS Organizations?",
+ description: "Use AWS Organizations to automate spoke account registration.",
allowedValues: ["Yes", "No"],
default: "No",
});
@@ -201,7 +202,8 @@ export class AwsInstanceSchedulerStack extends cdk.Stack {
const principals = new cdk.CfnParameter(this, "Principals", {
type: "CommaDelimitedList",
description:
- "(Required) If using AWS Organizations, provide Organization ID. Eg. o-xxxxyyy. Else, comma separated list of remote account ids. Eg.: 1111111111, 2222222222 or {param: ssm-param-name}",
+ "(Required) If using AWS Organizations, provide the Organization ID. Eg. o-xxxxyyy. " +
+ "Else, provide a comma separated list of spoke account ids to schedule. Eg.: 1111111111, 2222222222 or {param: ssm-param-name}",
default: props.paramOverrides?.principals ?? "",
});
@@ -215,15 +217,19 @@ export class AwsInstanceSchedulerStack extends cdk.Stack {
const startedTags = new cdk.CfnParameter(this, "StartedTags", {
type: "String",
description:
- "Comma separated list of tagname and values on the formt name=value,name=value,.. that are set on started instances",
- default: props.paramOverrides?.startedTags ?? "",
+ "Comma separated list of tag keys and values of the format key=value, key=value,... that are set on started instances. Leave blank to disable.",
+ default:
+ props.paramOverrides?.startedTags ??
+ "InstanceScheduler-LastAction=Started By {scheduler} {year}/{month}/{day} {hour}:{minute}{timezone}, ",
});
const stoppedTags = new cdk.CfnParameter(this, "StoppedTags", {
type: "String",
description:
- "Comma separated list of tagname and values on the formt name=value,name=value,.. that are set on stopped instances",
- default: props.paramOverrides?.stoppedTags ?? "",
+ "Comma separated list of tag keys and values of the format key=value, key=value,... that are set on stopped instances. Leave blank to disable.",
+ default:
+ props.paramOverrides?.stoppedTags ??
+ "InstanceScheduler-LastAction=Stopped By {scheduler} {year}/{month}/{day} {hour}:{minute}{timezone}, ",
});
const schedulerFrequency = new cdk.CfnParameter(this, "SchedulerFrequency", {
@@ -270,7 +276,11 @@ export class AwsInstanceSchedulerStack extends cdk.Stack {
mappings.setValue("SchedulerEventBusName", "Name", "scheduler-event-bus");
const send = new cdk.CfnMapping(this, "Send");
- send.setValue("AnonymousUsage", "Data", "Yes");
+ if (props.disableOpMetrics) {
+ send.setValue("AnonymousUsage", "Data", "No");
+ } else {
+ send.setValue("AnonymousUsage", "Data", "Yes");
+ }
send.setValue("ParameterKey", "UniqueId", `/Solutions/${props.solutionName}/UUID/`);
//End Mappings for instance scheduler.
@@ -308,7 +318,7 @@ export class AwsInstanceSchedulerStack extends cdk.Stack {
//Start scheduler role reference and related references of principle, policy statement, and policy document.
const compositePrincipal = new iam.CompositePrincipal(
new iam.ServicePrincipal("events.amazonaws.com"),
- new iam.ServicePrincipal("lambda.amazonaws.com")
+ new iam.ServicePrincipal("lambda.amazonaws.com"),
);
const schedulerRole = new iam.Role(this, "SchedulerRole", {
@@ -356,6 +366,20 @@ export class AwsInstanceSchedulerStack extends cdk.Stack {
masterKey: instanceSchedulerEncryptionKey,
});
+ const conditionScheduleEc2 = new cdk.CfnCondition(this, "ScheduleEC2", {
+ expression: cdk.Fn.conditionOr(
+ cdk.Fn.conditionEquals(scheduledServices.valueAsString, "EC2"),
+ cdk.Fn.conditionEquals(scheduledServices.valueAsString, "Both"),
+ ),
+ });
+
+ const conditionScheduleRds = new cdk.CfnCondition(this, "ScheduleRDS", {
+ expression: cdk.Fn.conditionOr(
+ cdk.Fn.conditionEquals(scheduledServices.valueAsString, "RDS"),
+ cdk.Fn.conditionEquals(scheduledServices.valueAsString, "Both"),
+ ),
+ });
+
//instance scheduler core scheduler construct reference.
const coreScheduler = new CoreScheduler(this, {
solutionVersion: props.solutionVersion,
@@ -364,21 +388,34 @@ export class AwsInstanceSchedulerStack extends cdk.Stack {
kmsEncryptionKey: instanceSchedulerEncryptionKey,
environment: {
SCHEDULER_FREQUENCY: schedulerFrequency.valueAsString,
- TAG_NAME: tagName.valueAsString,
LOG_GROUP: schedulerLogGroup.logGroupName,
ACCOUNT: this.account,
ISSUES_TOPIC_ARN: snsTopic.topicArn,
STACK_NAME: Aws.STACK_NAME,
SEND_METRICS: mappings.findInMap("TrueFalse", send.findInMap("AnonymousUsage", "Data")),
SOLUTION_ID: mappings.findInMap("Settings", "MetricsSolutionId"),
+ SOLUTION_VERSION: props.solutionVersion,
TRACE: mappings.findInMap("TrueFalse", trace.valueAsString),
- ENABLE_SSM_MAINTENANCE_WINDOWS: mappings.findInMap("TrueFalse", enableSSMMaintenanceWindows.valueAsString),
- USER_AGENT: "InstanceScheduler-" + Aws.STACK_NAME + "-" + props.solutionVersion,
USER_AGENT_EXTRA: `AwsSolution/${props.solutionId}/${props.solutionVersion}`,
METRICS_URL: mappings.findInMap("Settings", "MetricsUrl"),
STACK_ID: `${cdk.Aws.STACK_ID}`,
UUID_KEY: send.findInMap("ParameterKey", "UniqueId"),
START_EC2_BATCH_SIZE: "5",
+ SCHEDULE_TAG_KEY: tagName.valueAsString,
+ DEFAULT_TIMEZONE: defaultTimezone.valueAsString,
+ ENABLE_CLOUDWATCH_METRICS: mappings.findInMap("TrueFalse", useCloudWatchMetrics.valueAsString),
+ ENABLE_EC2_SERVICE: cdk.Fn.conditionIf(conditionScheduleEc2.logicalId, "True", "False").toString(),
+ ENABLE_RDS_SERVICE: cdk.Fn.conditionIf(conditionScheduleRds.logicalId, "True", "False").toString(),
+ ENABLE_RDS_CLUSTERS: mappings.findInMap("TrueFalse", scheduleRdsClusters.valueAsString),
+ ENABLE_RDS_SNAPSHOTS: mappings.findInMap("TrueFalse", createRdsSnapshot.valueAsString),
+ SCHEDULE_REGIONS: cdk.Fn.join(",", regions.valueAsList),
+ APP_NAMESPACE: namespace.valueAsString,
+ SCHEDULER_ROLE_NAME: mappings.findInMap("SchedulerRole", "Name"),
+ ENABLE_SCHEDULE_HUB_ACCOUNT: mappings.findInMap("TrueFalse", scheduleLambdaAccount.valueAsString),
+ ENABLE_EC2_SSM_MAINTENANCE_WINDOWS: mappings.findInMap("TrueFalse", enableSSMMaintenanceWindows.valueAsString),
+ START_TAGS: startedTags.valueAsString,
+ STOP_TAGS: stoppedTags.valueAsString,
+ ENABLE_AWS_ORGANIZATIONS: mappings.findInMap("TrueFalse", usingAWSOrganizations.valueAsString),
},
});
@@ -408,7 +445,7 @@ export class AwsInstanceSchedulerStack extends cdk.Stack {
effect: Effect.ALLOW,
resources: [
cdk.Fn.sub(
- "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/Solutions/aws-instance-scheduler/UUID/*"
+ `arn:\${AWS::Partition}:ssm:\${AWS::Region}:\${AWS::AccountId}:parameter/Solutions/${props.solutionName}/UUID/*`,
),
],
});
@@ -419,14 +456,38 @@ export class AwsInstanceSchedulerStack extends cdk.Stack {
description:
"Instance Scheduler - Rule to trigger instance for scheduler function version " + props["solutionVersion"],
schedule: events.Schedule.expression(mappings.findInMap("Timeouts", schedulerFrequency.valueAsString)),
+ targets: [
+ new EBEventTarget.LambdaFunction(coreScheduler.lambdaFunction, {
+ event: events.RuleTargetInput.fromObject({
+ scheduled_action: "run_orchestrator",
+ }),
+ }),
+ ],
});
- schedulerRule.addTarget(new LambdaFunction(coreScheduler.lambdaFunction));
+ const cfnSchedulerRule = schedulerRule.node.defaultChild as events.CfnRule;
+ cfnSchedulerRule.addPropertyOverride(
+ "State",
+ mappings.findInMap("EnabledDisabled", schedulingActive.valueAsString),
+ );
- const eventRule_cfn_ref = schedulerRule.node.defaultChild as events.CfnRule;
- eventRule_cfn_ref.addPropertyOverride(
+ const configurationMetricsRule = new events.Rule(this, "ConfigurationMetricsEventRule", {
+ description:
+ "Instance Scheduler - Rule to trigger gathering of weekly anonymized operational metrics for Instance Scheduler",
+ schedule: events.Schedule.expression("rate(7 days)"),
+ targets: [
+ new EBEventTarget.LambdaFunction(coreScheduler.lambdaFunction, {
+ event: events.RuleTargetInput.fromObject({
+ scheduled_action: "collect_configuration_metrics",
+ }),
+ }),
+ ],
+ });
+
+ const cfnConfigurationMetricsRule = configurationMetricsRule.node.defaultChild as events.CfnRule;
+ cfnConfigurationMetricsRule.addPropertyOverride(
"State",
- mappings.findInMap("EnabledDisabled", schedulingActive.valueAsString)
+ mappings.findInMap("EnabledDisabled", send.findInMap("AnonymousUsage", "Data")),
);
//End instance scheduler aws-event-lambda construct reference.
@@ -439,7 +500,6 @@ export class AwsInstanceSchedulerStack extends cdk.Stack {
resourceType: "Custom::ServiceSetup",
properties: {
timeout: 120,
- config_table: (coreScheduler.configTable.node.defaultChild as dynamodb.CfnTable).ref,
tagname: tagName,
default_timezone: defaultTimezone,
use_metrics: mappings.findInMap("TrueFalse", useCloudWatchMetrics.valueAsString),
@@ -453,7 +513,7 @@ export class AwsInstanceSchedulerStack extends cdk.Stack {
scheduler_role_name: mappings.findInMap("SchedulerRole", "Name"),
schedule_lambda_account: mappings.findInMap("TrueFalse", scheduleLambdaAccount.valueAsString),
trace: mappings.findInMap("TrueFalse", trace.valueAsString),
- enable_SSM_maintenance_windows: mappings.findInMap("TrueFalse", enableSSMMaintenanceWindows.valueAsString),
+ enable_ssm_maintenance_windows: mappings.findInMap("TrueFalse", enableSSMMaintenanceWindows.valueAsString),
log_retention_days: logRetention.valueAsNumber,
started_tags: startedTags.valueAsString,
stopped_tags: stoppedTags.valueAsString,
@@ -503,11 +563,9 @@ export class AwsInstanceSchedulerStack extends cdk.Stack {
const ec2PolicyStatementforMisc = new PolicyStatement({
actions: [
- "logs:DescribeLogStreams",
"rds:DescribeDBClusters",
"rds:DescribeDBInstances",
"ec2:DescribeInstances",
- "ec2:DescribeRegions",
"cloudwatch:PutMetricData",
"ssm:DescribeMaintenanceWindows",
"tag:GetResources",
@@ -593,7 +651,7 @@ export class AwsInstanceSchedulerStack extends cdk.Stack {
effect: Effect.ALLOW,
resources: [
cdk.Fn.sub(
- "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${AWS::StackName}-InstanceSchedulerMain"
+ "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${AWS::StackName}-InstanceSchedulerMain",
),
],
});
@@ -666,6 +724,13 @@ export class AwsInstanceSchedulerStack extends cdk.Stack {
},
};
+ NagSuppressions.addResourceSuppressions(lambdaFunction, [
+ {
+ id: "AwsSolutions-L1",
+ reason: "Lambda runtime held back to the newest supported by all partitions",
+ },
+ ]);
+
//Cloud Formation cfn references for ensuring the resource names are similar to earlier releases, and additional metadata for the cfn nag rules.
const instanceSchedulerEncryptionKey_cfn_ref = instanceSchedulerEncryptionKey.node.defaultChild as kms.CfnKey;
instanceSchedulerEncryptionKey_cfn_ref.overrideLogicalId("InstanceSchedulerEncryptionKey");
@@ -730,7 +795,6 @@ export class AwsInstanceSchedulerStack extends cdk.Stack {
"CreateRdsSnapshot",
"SchedulingActive",
"DefaultTimezone",
- "CrossAccountRoles",
"ScheduleLambdaAccount",
"SchedulerFrequency",
"MemorySize",
@@ -759,7 +823,7 @@ export class AwsInstanceSchedulerStack extends cdk.Stack {
],
ParameterLabels: {
Namespace: {
- default: "Provide a unique namespace value.",
+ default: "Namespace",
},
LogRetentionDays: {
default: "Log retention days",
@@ -774,10 +838,10 @@ export class AwsInstanceSchedulerStack extends cdk.Stack {
default: "Scheduling enabled",
},
UsingAWSOrganizations: {
- default: "Using AWS Organizations?",
+ default: "Use AWS Organizations",
},
Principals: {
- default: "Provide Organization Id OR List of Remote Account Ids",
+ default: "Organization Id/Remote Account Ids",
},
ScheduleLambdaAccount: {
default: "This account",
diff --git a/source/infrastructure/instance-scheduler/lib/aws-instance-scheduler-remote-stack.ts b/source/instance-scheduler/lib/remote-stack.ts
similarity index 92%
rename from source/infrastructure/instance-scheduler/lib/aws-instance-scheduler-remote-stack.ts
rename to source/instance-scheduler/lib/remote-stack.ts
index b42dc77b..57e44337 100644
--- a/source/infrastructure/instance-scheduler/lib/aws-instance-scheduler-remote-stack.ts
+++ b/source/instance-scheduler/lib/remote-stack.ts
@@ -11,7 +11,7 @@ import { Construct } from "constructs";
import { AppRegistryForInstanceScheduler } from "./app-registry";
import { NagSuppressions } from "cdk-nag";
-export interface AwsInstanceSchedulerRemoteStackProps extends cdk.StackProps {
+export interface InstanceSchedulerRemoteStackProps extends cdk.StackProps {
readonly description: string;
readonly solutionId: string;
readonly solutionName: string;
@@ -20,13 +20,14 @@ export interface AwsInstanceSchedulerRemoteStackProps extends cdk.StackProps {
readonly appregSolutionName: string;
}
-export class AwsInstanceSchedulerRemoteStack extends cdk.Stack {
- constructor(scope: Construct, id: string, props: AwsInstanceSchedulerRemoteStackProps) {
+export class InstanceSchedulerRemoteStack extends cdk.Stack {
+ constructor(scope: Construct, id: string, props: InstanceSchedulerRemoteStackProps) {
super(scope, id, props);
//CFN Parameters
const instanceSchedulerAccount = new cdk.CfnParameter(this, "InstanceSchedulerAccount", {
- description: "Instance Scheduler Hub Account number to manage EC2 and RDS Resources in this account.",
+ description:
+ "AccountID of the Instance Scheduler Hub stack that should be allowed to schedule resources in this account.",
type: "String",
allowedPattern: "(^[0-9]{12}$)",
constraintDescription: "Account number is a 12 digit number",
@@ -35,12 +36,15 @@ export class AwsInstanceSchedulerRemoteStack extends cdk.Stack {
const namespace = new cdk.CfnParameter(this, "Namespace", {
type: "String",
description:
- "Unique identifier used to differentiate between multiple solution deployments. Example: Test or Prod",
+ "Unique identifier used to differentiate between multiple solution deployments. " +
+ "Must be set to the same value as the Hub stack",
});
const usingAWSOrganizations = new cdk.CfnParameter(this, "UsingAWSOrganizations", {
type: "String",
- description: "Use this setting to automate spoke account enrollment if using AWS Organizations.",
+ description:
+ "Use AWS Organizations to automate spoke account registration. " +
+ "Must be set to the same value as the Hub stack",
allowedValues: ["Yes", "No"],
default: "No",
});
@@ -65,7 +69,7 @@ export class AwsInstanceSchedulerRemoteStack extends cdk.Stack {
const accountPrincipal = new ArnPrincipal(
cdk.Fn.sub("arn:${AWS::Partition}:iam::${accountId}:root", {
accountId: instanceSchedulerAccount.valueAsString,
- })
+ }),
);
const servicePrincipal = new iam.ServicePrincipal("lambda.amazonaws.com");
@@ -121,7 +125,6 @@ export class AwsInstanceSchedulerRemoteStack extends cdk.Stack {
"rds:DescribeDBClusters",
"rds:DescribeDBInstances",
"ec2:DescribeInstances",
- "ec2:DescribeRegions",
"ssm:DescribeMaintenanceWindows",
"ssm:DescribeMaintenanceWindowExecutions",
"tag:GetResources",
@@ -180,7 +183,7 @@ export class AwsInstanceSchedulerRemoteStack extends cdk.Stack {
"arn:${AWS::Partition}:events:${AWS::Region}:${InstanceSchedulerAccount}:event-bus/${Namespace}-${EventBusName}",
{
EventBusName: mappings.findInMap("SchedulerEventBusName", "Name"),
- }
+ },
),
],
}),
@@ -197,7 +200,7 @@ export class AwsInstanceSchedulerRemoteStack extends cdk.Stack {
"arn:${AWS::Partition}:events:${AWS::Region}:${InstanceSchedulerAccount}:event-bus/${Namespace}-${EventBusName}",
{
EventBusName: mappings.findInMap("SchedulerEventBusName", "Name"),
- }
+ },
),
id: "Spoke-SSM-Parameter-Event",
roleArn: schedulerEventDeliveryRole.roleArn,
@@ -273,19 +276,16 @@ export class AwsInstanceSchedulerRemoteStack extends cdk.Stack {
Parameters: ["Namespace"],
},
{
- Label: { default: "Instance Scheduler Hub Account Configuration" },
+ Label: { default: "Account Structure" },
Parameters: ["InstanceSchedulerAccount", "UsingAWSOrganizations"],
},
],
ParameterLabels: {
- Namespace: {
- default: "Provide the same unique namespace value defined in the hub stack.",
- },
InstanceSchedulerAccount: {
- default: "Instance Scheduler Hub Account ID",
+ default: "Hub Account ID",
},
UsingAWSOrganizations: {
- default: "Set this value to match hub stack CloudFormation parameter.",
+ default: "Use AWS Organizations",
},
},
},
diff --git a/source/infrastructure/instance-scheduler/lib/time-zones.ts b/source/instance-scheduler/lib/time-zones.ts
similarity index 100%
rename from source/infrastructure/instance-scheduler/lib/time-zones.ts
rename to source/instance-scheduler/lib/time-zones.ts
diff --git a/source/infrastructure/instance-scheduler/tests/__snapshots__/aws-instance-scheduler-remote-stack.test.ts.snap b/source/instance-scheduler/tests/__snapshots__/instance-scheduler-remote-stack.test.ts.snap
similarity index 87%
rename from source/infrastructure/instance-scheduler/tests/__snapshots__/aws-instance-scheduler-remote-stack.test.ts.snap
rename to source/instance-scheduler/tests/__snapshots__/instance-scheduler-remote-stack.test.ts.snap
index 8b2d8a93..3e31943c 100644
--- a/source/infrastructure/instance-scheduler/tests/__snapshots__/aws-instance-scheduler-remote-stack.test.ts.snap
+++ b/source/instance-scheduler/tests/__snapshots__/instance-scheduler-remote-stack.test.ts.snap
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
+exports[`InstanceSchedulerRemoteStack snapshot test 1`] = `
{
"AWSTemplateFormatVersion": "2010-09-09",
"Conditions": {
@@ -20,7 +20,7 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"AppRegistryApplicationName": "instance-scheduler-on-aws",
"ApplicationType": "AWS-Solutions",
"ID": "SO0030",
- "SolutionName": "aws-instance-scheduler",
+ "SolutionName": "instance-scheduler-on-aws",
"Version": "v1.5.0",
},
},
@@ -38,55 +38,33 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"ParameterGroups": [
{
"Label": {
- "default": "Account",
+ "default": "Namespace Configuration",
+ },
+ "Parameters": [
+ "Namespace",
+ ],
+ },
+ {
+ "Label": {
+ "default": "Account Structure",
},
"Parameters": [
"InstanceSchedulerAccount",
+ "UsingAWSOrganizations",
],
},
],
"ParameterLabels": {
"InstanceSchedulerAccount": {
- "default": "Primary account",
+ "default": "Hub Account ID",
+ },
+ "UsingAWSOrganizations": {
+ "default": "Use AWS Organizations",
},
},
},
},
"Outputs": {
- "AppRegistryApplicationManagerUrl775D5C3D": {
- "Description": "Application manager url for the application created.",
- "Value": {
- "Fn::Join": [
- "",
- [
- "https://eu-west-1.console.aws.amazon.com/systems-manager/appmanager/application/AWS_AppRegistry_Application-",
- {
- "Fn::Join": [
- "-",
- [
- {
- "Fn::FindInMap": [
- "AppRegistryForInstanceSchedulerSolution25A90F05",
- "Data",
- "AppRegistryApplicationName",
- ],
- },
- {
- "Ref": "AWS::Region",
- },
- {
- "Ref": "AWS::AccountId",
- },
- {
- "Ref": "AWS::StackName",
- },
- ],
- ],
- },
- ],
- ],
- },
- },
"CrossAccountRole": {
"Description": "Arn for cross account role for Instance scheduler, add this arn to the list of crossaccount roles (CrossAccountRoles) parameter of the Instance Scheduler template.",
"Value": {
@@ -101,11 +79,11 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"InstanceSchedulerAccount": {
"AllowedPattern": "(^[0-9]{12}$)",
"ConstraintDescription": "Account number is a 12 digit number",
- "Description": "Instance Scheduler Hub Account number to manage EC2 and RDS Resources in this account.",
+ "Description": "AccountID of the Instance Scheduler Hub stack that should be allowed to schedule resources in this account.",
"Type": "String",
},
"Namespace": {
- "Description": "Unique identifier used to differentiate between multiple solution deployments. Example: Test or Prod",
+ "Description": "Unique identifier used to differentiate between multiple solution deployments. Must be set to the same value as the Hub stack",
"Type": "String",
},
"UsingAWSOrganizations": {
@@ -114,7 +92,7 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"No",
],
"Default": "No",
- "Description": "Use this setting to automate spoke account enrollment if using AWS Organizations.",
+ "Description": "Use AWS Organizations to automate spoke account registration. Must be set to the same value as the Hub stack",
"Type": "String",
},
},
@@ -192,7 +170,22 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
},
"Type": "AWS::ServiceCatalogAppRegistry::Application",
},
- "AppRegistryAttributeGroupAssociation2328adb27afd49C57352": {
+ "AppRegistryAssociation": {
+ "Properties": {
+ "Application": {
+ "Fn::GetAtt": [
+ "AppRegistry968496A3",
+ "Id",
+ ],
+ },
+ "Resource": {
+ "Ref": "AWS::StackId",
+ },
+ "ResourceType": "CFN_STACK",
+ },
+ "Type": "AWS::ServiceCatalogAppRegistry::ResourceAssociation",
+ },
+ "AppRegistryAttributeGroupAssociationf823ba38a843A987197E": {
"Properties": {
"Application": {
"Fn::GetAtt": [
@@ -202,14 +195,14 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
},
"AttributeGroup": {
"Fn::GetAtt": [
- "AppRegistryForInstanceSchedulerDefaultApplicationAttributes78274898",
+ "AppRegistryDefaultApplicationAttributes15279635",
"Id",
],
},
},
"Type": "AWS::ServiceCatalogAppRegistry::AttributeGroupAssociation",
},
- "AppRegistryForInstanceSchedulerDefaultApplicationAttributes78274898": {
+ "AppRegistryDefaultApplicationAttributes15279635": {
"Properties": {
"Attributes": {
"applicationType": {
@@ -244,34 +237,57 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"Description": "Attribute group for solution information",
"Name": {
"Fn::Join": [
- "-",
+ "",
[
+ "attgroup-",
{
- "Ref": "AWS::Region",
- },
- {
- "Ref": "AWS::StackName",
+ "Fn::Join": [
+ "-",
+ [
+ {
+ "Ref": "AWS::Region",
+ },
+ {
+ "Ref": "AWS::StackName",
+ },
+ ],
+ ],
},
],
],
},
- },
- "Type": "AWS::ServiceCatalogAppRegistry::AttributeGroup",
- },
- "AppRegistryResourceAssociationdf1bce20c35e43B5355E": {
- "Properties": {
- "Application": {
- "Fn::GetAtt": [
- "AppRegistry968496A3",
- "Id",
- ],
- },
- "Resource": {
- "Ref": "AWS::StackId",
+ "Tags": {
+ "Solutions:ApplicationType": {
+ "Fn::FindInMap": [
+ "AppRegistryForInstanceSchedulerSolution25A90F05",
+ "Data",
+ "ApplicationType",
+ ],
+ },
+ "Solutions:SolutionID": {
+ "Fn::FindInMap": [
+ "AppRegistryForInstanceSchedulerSolution25A90F05",
+ "Data",
+ "ID",
+ ],
+ },
+ "Solutions:SolutionName": {
+ "Fn::FindInMap": [
+ "AppRegistryForInstanceSchedulerSolution25A90F05",
+ "Data",
+ "SolutionName",
+ ],
+ },
+ "Solutions:SolutionVersion": {
+ "Fn::FindInMap": [
+ "AppRegistryForInstanceSchedulerSolution25A90F05",
+ "Data",
+ "Version",
+ ],
+ },
},
- "ResourceType": "CFN_STACK",
},
- "Type": "AWS::ServiceCatalogAppRegistry::ResourceAssociation",
+ "Type": "AWS::ServiceCatalogAppRegistry::AttributeGroup",
},
"EC2SchedulerCrossAccountRole": {
"Metadata": {
@@ -387,7 +403,6 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"rds:DescribeDBClusters",
"rds:DescribeDBInstances",
"ec2:DescribeInstances",
- "ec2:DescribeRegions",
"ssm:DescribeMaintenanceWindows",
"ssm:DescribeMaintenanceWindowExecutions",
"tag:GetResources",
diff --git a/source/infrastructure/instance-scheduler/tests/__snapshots__/aws-instance-scheduler-stack.test.ts.snap b/source/instance-scheduler/tests/__snapshots__/instance-scheduler-stack.test.ts.snap
similarity index 86%
rename from source/infrastructure/instance-scheduler/tests/__snapshots__/aws-instance-scheduler-stack.test.ts.snap
rename to source/instance-scheduler/tests/__snapshots__/instance-scheduler-stack.test.ts.snap
index 7f0e53c2..097cf8f4 100644
--- a/source/infrastructure/instance-scheduler/tests/__snapshots__/aws-instance-scheduler-stack.test.ts.snap
+++ b/source/instance-scheduler/tests/__snapshots__/instance-scheduler-stack.test.ts.snap
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
+exports[`InstanceSchedulerStack snapshot test 1`] = `
{
"AWSTemplateFormatVersion": "2010-09-09",
"Conditions": {
@@ -12,6 +12,46 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"Yes",
],
},
+ "ScheduleEC2": {
+ "Fn::Or": [
+ {
+ "Fn::Equals": [
+ {
+ "Ref": "ScheduledServices",
+ },
+ "EC2",
+ ],
+ },
+ {
+ "Fn::Equals": [
+ {
+ "Ref": "ScheduledServices",
+ },
+ "Both",
+ ],
+ },
+ ],
+ },
+ "ScheduleRDS": {
+ "Fn::Or": [
+ {
+ "Fn::Equals": [
+ {
+ "Ref": "ScheduledServices",
+ },
+ "RDS",
+ ],
+ },
+ {
+ "Fn::Equals": [
+ {
+ "Ref": "ScheduledServices",
+ },
+ "Both",
+ ],
+ },
+ ],
+ },
},
"Description": "",
"Mappings": {
@@ -20,7 +60,7 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"AppRegistryApplicationName": "instance-scheduler-on-aws",
"ApplicationType": "AWS-Solutions",
"ID": "SO0030",
- "SolutionName": "aws-instance-scheduler",
+ "SolutionName": "instance-scheduler-on-aws",
"Version": "v1.5.0",
},
},
@@ -29,7 +69,7 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"Data": "Yes",
},
"ParameterKey": {
- "UniqueId": "/Solutions/aws-instance-scheduler/UUID/",
+ "UniqueId": "/Solutions/instance-scheduler-on-aws/UUID/",
},
},
"mappings": {
@@ -72,7 +112,7 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"ParameterGroups": [
{
"Label": {
- "default": "Scheduler (version v1.4.0)",
+ "default": "Scheduler (version v1.5.0)",
},
"Parameters": [
"TagName",
@@ -80,22 +120,38 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"ScheduleRdsClusters",
"CreateRdsSnapshot",
"SchedulingActive",
- "Regions",
"DefaultTimezone",
- "CrossAccountRoles",
"ScheduleLambdaAccount",
"SchedulerFrequency",
"MemorySize",
],
},
+ {
+ "Label": {
+ "default": "Namespace Configuration",
+ },
+ "Parameters": [
+ "Namespace",
+ ],
+ },
+ {
+ "Label": {
+ "default": "Account Structure",
+ },
+ "Parameters": [
+ "UsingAWSOrganizations",
+ "Principals",
+ "Regions",
+ ],
+ },
{
"Label": {
"default": "Options",
},
"Parameters": [
"UseCloudWatchMetrics",
- "SendAnonymousData",
"Trace",
+ "EnableSSMMaintenanceWindows",
],
},
{
@@ -113,18 +169,24 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"CreateRdsSnapshot": {
"default": "Create RDS instance snapshot",
},
- "CrossAccountRoles": {
- "default": "Cross-account roles",
- },
"DefaultTimezone": {
"default": "Default time zone",
},
+ "EnableSSMMaintenanceWindows": {
+ "default": "Enable SSM Maintenance windows",
+ },
"LogRetentionDays": {
"default": "Log retention days",
},
"MemorySize": {
"default": "Memory size",
},
+ "Namespace": {
+ "default": "Namespace",
+ },
+ "Principals": {
+ "default": "Organization Id/Remote Account Ids",
+ },
"Regions": {
"default": "Region(s)",
},
@@ -143,9 +205,6 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"SchedulingActive": {
"default": "Scheduling enabled",
},
- "SendAnonymousData": {
- "default": "Send anonymous usage data",
- },
"StartedTags": {
"default": "Started tags",
},
@@ -156,11 +215,14 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"default": "Instance Scheduler tag name",
},
"Trace": {
- "default": "Enable CloudWatch Logs",
+ "default": "Enable CloudWatch Debug Logs",
},
"UseCloudWatchMetrics": {
"default": "Enable CloudWatch Metrics",
},
+ "UsingAWSOrganizations": {
+ "default": "Use AWS Organizations",
+ },
},
},
},
@@ -169,40 +231,6 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"Description": "Account to give access to when creating cross-account access role for cross account scenario ",
"Value": "111111111111",
},
- "AppRegistryApplicationManagerUrl775D5C3D": {
- "Description": "Application manager url for the application created.",
- "Value": {
- "Fn::Join": [
- "",
- [
- "https://eu-west-1.console.aws.amazon.com/systems-manager/appmanager/application/AWS_AppRegistry_Application-",
- {
- "Fn::Join": [
- "-",
- [
- {
- "Fn::FindInMap": [
- "AppRegistryForInstanceSchedulerSolution25A90F05",
- "Data",
- "AppRegistryApplicationName",
- ],
- },
- {
- "Ref": "AWS::Region",
- },
- {
- "Ref": "AWS::AccountId",
- },
- {
- "Ref": "AWS::StackName",
- },
- ],
- ],
- },
- ],
- ],
- },
- },
"ConfigurationTable": {
"Description": "Name of the DynamoDB configuration table",
"Value": {
@@ -743,12 +771,12 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
},
"Principals": {
"Default": "",
- "Description": "(Required) If using AWS Organizations, provide Organization ID. Eg. o-xxxxyyy. Else, comma separated list of remote account ids. Eg.: 1111111111, 2222222222 or {param: ssm-param-name}",
+ "Description": "(Required) If using AWS Organizations, provide the Organization ID. Eg. o-xxxxyyy. Else, provide a comma separated list of spoke account ids to schedule. Eg.: 1111111111, 2222222222 or {param: ssm-param-name}",
"Type": "CommaDelimitedList",
},
"Regions": {
"Default": "",
- "Description": "List of regions in which instances are scheduled, leave blank for current region only.",
+ "Description": "List of regions in which instances should be scheduled, leave blank for current region only.",
"Type": "CommaDelimitedList",
},
"ScheduleLambdaAccount": {
@@ -803,13 +831,13 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"Type": "String",
},
"StartedTags": {
- "Default": "",
- "Description": "Comma separated list of tagname and values on the formt name=value,name=value,.. that are set on started instances",
+ "Default": "InstanceScheduler-LastAction=Started By {scheduler} {year}/{month}/{day} {hour}:{minute}{timezone}, ",
+ "Description": "Comma separated list of tag keys and values of the format key=value, key=value,... that are set on started instances. Leave blank to disable.",
"Type": "String",
},
"StoppedTags": {
- "Default": "",
- "Description": "Comma separated list of tagname and values on the formt name=value,name=value,.. that are set on stopped instances",
+ "Default": "InstanceScheduler-LastAction=Stopped By {scheduler} {year}/{month}/{day} {hour}:{minute}{timezone}, ",
+ "Description": "Comma separated list of tag keys and values of the format key=value, key=value,... that are set on stopped instances. Leave blank to disable.",
"Type": "String",
},
"TagName": {
@@ -843,7 +871,7 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"No",
],
"Default": "No",
- "Description": "Is the hub account member of the AWS Organizations?",
+ "Description": "Use AWS Organizations to automate spoke account registration.",
"Type": "String",
},
},
@@ -921,7 +949,22 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
},
"Type": "AWS::ServiceCatalogAppRegistry::Application",
},
- "AppRegistryAttributeGroupAssociation2328adb27afd49C57352": {
+ "AppRegistryAssociation": {
+ "Properties": {
+ "Application": {
+ "Fn::GetAtt": [
+ "AppRegistry968496A3",
+ "Id",
+ ],
+ },
+ "Resource": {
+ "Ref": "AWS::StackId",
+ },
+ "ResourceType": "CFN_STACK",
+ },
+ "Type": "AWS::ServiceCatalogAppRegistry::ResourceAssociation",
+ },
+ "AppRegistryAttributeGroupAssociationf823ba38a843A987197E": {
"Properties": {
"Application": {
"Fn::GetAtt": [
@@ -931,14 +974,14 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
},
"AttributeGroup": {
"Fn::GetAtt": [
- "AppRegistryForInstanceSchedulerDefaultApplicationAttributes78274898",
+ "AppRegistryDefaultApplicationAttributes15279635",
"Id",
],
},
},
"Type": "AWS::ServiceCatalogAppRegistry::AttributeGroupAssociation",
},
- "AppRegistryForInstanceSchedulerDefaultApplicationAttributes78274898": {
+ "AppRegistryDefaultApplicationAttributes15279635": {
"Properties": {
"Attributes": {
"applicationType": {
@@ -973,34 +1016,57 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"Description": "Attribute group for solution information",
"Name": {
"Fn::Join": [
- "-",
+ "",
[
+ "attgroup-",
{
- "Ref": "AWS::Region",
- },
- {
- "Ref": "AWS::StackName",
+ "Fn::Join": [
+ "-",
+ [
+ {
+ "Ref": "AWS::Region",
+ },
+ {
+ "Ref": "AWS::StackName",
+ },
+ ],
+ ],
},
],
],
},
- },
- "Type": "AWS::ServiceCatalogAppRegistry::AttributeGroup",
- },
- "AppRegistryResourceAssociationdf1bce20c35e43B5355E": {
- "Properties": {
- "Application": {
- "Fn::GetAtt": [
- "AppRegistry968496A3",
- "Id",
- ],
- },
- "Resource": {
- "Ref": "AWS::StackId",
+ "Tags": {
+ "Solutions:ApplicationType": {
+ "Fn::FindInMap": [
+ "AppRegistryForInstanceSchedulerSolution25A90F05",
+ "Data",
+ "ApplicationType",
+ ],
+ },
+ "Solutions:SolutionID": {
+ "Fn::FindInMap": [
+ "AppRegistryForInstanceSchedulerSolution25A90F05",
+ "Data",
+ "ID",
+ ],
+ },
+ "Solutions:SolutionName": {
+ "Fn::FindInMap": [
+ "AppRegistryForInstanceSchedulerSolution25A90F05",
+ "Data",
+ "SolutionName",
+ ],
+ },
+ "Solutions:SolutionVersion": {
+ "Fn::FindInMap": [
+ "AppRegistryForInstanceSchedulerSolution25A90F05",
+ "Data",
+ "Version",
+ ],
+ },
},
- "ResourceType": "CFN_STACK",
},
- "Type": "AWS::ServiceCatalogAppRegistry::ResourceAssociation",
+ "Type": "AWS::ServiceCatalogAppRegistry::AttributeGroup",
},
"ConfigTable": {
"DeletionPolicy": "Delete",
@@ -1040,6 +1106,57 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"Type": "AWS::DynamoDB::Table",
"UpdateReplacePolicy": "Delete",
},
+ "ConfigurationMetricsEventRule8BE742A8": {
+ "Properties": {
+ "Description": "Instance Scheduler - Rule to trigger gathering of weekly anonymized operational metrics for Instance Scheduler",
+ "ScheduleExpression": "rate(7 days)",
+ "State": {
+ "Fn::FindInMap": [
+ "mappings",
+ "EnabledDisabled",
+ {
+ "Fn::FindInMap": [
+ "Send",
+ "AnonymousUsage",
+ "Data",
+ ],
+ },
+ ],
+ },
+ "Targets": [
+ {
+ "Arn": {
+ "Fn::GetAtt": [
+ "Main",
+ "Arn",
+ ],
+ },
+ "Id": "Target0",
+ "Input": "{"scheduled_action":"collect_configuration_metrics"}",
+ },
+ ],
+ },
+ "Type": "AWS::Events::Rule",
+ },
+ "ConfigurationMetricsEventRuleAllowEventRulestackschedulerlambdaC9E2D53DBDC7CFFA": {
+ "Properties": {
+ "Action": "lambda:InvokeFunction",
+ "FunctionName": {
+ "Fn::GetAtt": [
+ "Main",
+ "Arn",
+ ],
+ },
+ "Principal": "events.amazonaws.com",
+ "SourceArn": {
+ "Fn::GetAtt": [
+ "ConfigurationMetricsEventRule8BE742A8",
+ "Arn",
+ ],
+ },
+ },
+ "Type": "AWS::Lambda::Permission",
+ },
"EC2DynamoDBPolicy": {
"Metadata": {
"cdk_nag": {
@@ -1074,11 +1191,9 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
},
{
"Action": [
- "logs:DescribeLogStreams",
"rds:DescribeDBClusters",
"rds:DescribeDBInstances",
"ec2:DescribeInstances",
- "ec2:DescribeRegions",
"cloudwatch:PutMetricData",
"ssm:DescribeMaintenanceWindows",
"tag:GetResources",
@@ -1282,6 +1397,14 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"SchedulerRole",
],
"Metadata": {
+ "cdk_nag": {
+ "rules_to_suppress": [
+ {
+ "id": "AwsSolutions-L1",
+ "reason": "Lambda runtime held back to the newest supported by all partitions",
+ },
+ ],
+ },
"cfn_nag": {
"rules_to_suppress": [
{
@@ -1305,13 +1428,44 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"Environment": {
"Variables": {
"ACCOUNT": "111111111111",
+ "APP_NAMESPACE": {
+ "Ref": "Namespace",
+ },
"CONFIG_TABLE": {
"Ref": "ConfigTable",
},
"DDB_TABLE_NAME": {
"Ref": "StateTable",
},
- "ENABLE_SSM_MAINTENANCE_WINDOWS": {
+ "DEFAULT_TIMEZONE": {
+ "Ref": "DefaultTimezone",
+ },
+ "ENABLE_AWS_ORGANIZATIONS": {
+ "Fn::FindInMap": [
+ "mappings",
+ "TrueFalse",
+ {
+ "Ref": "UsingAWSOrganizations",
+ },
+ ],
+ },
+ "ENABLE_CLOUDWATCH_METRICS": {
+ "Fn::FindInMap": [
+ "mappings",
+ "TrueFalse",
+ {
+ "Ref": "UseCloudWatchMetrics",
+ },
+ ],
+ },
+ "ENABLE_EC2_SERVICE": {
+ "Fn::If": [
+ "ScheduleEC2",
+ "True",
+ "False",
+ ],
+ },
+ "ENABLE_EC2_SSM_MAINTENANCE_WINDOWS": {
"Fn::FindInMap": [
"mappings",
"TrueFalse",
@@ -1320,6 +1474,40 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
},
],
},
+ "ENABLE_RDS_CLUSTERS": {
+ "Fn::FindInMap": [
+ "mappings",
+ "TrueFalse",
+ {
+ "Ref": "ScheduleRdsClusters",
+ },
+ ],
+ },
+ "ENABLE_RDS_SERVICE": {
+ "Fn::If": [
+ "ScheduleRDS",
+ "True",
+ "False",
+ ],
+ },
+ "ENABLE_RDS_SNAPSHOTS": {
+ "Fn::FindInMap": [
+ "mappings",
+ "TrueFalse",
+ {
+ "Ref": "CreateRdsSnapshot",
+ },
+ ],
+ },
+ "ENABLE_SCHEDULE_HUB_ACCOUNT": {
+ "Fn::FindInMap": [
+ "mappings",
+ "TrueFalse",
+ {
+ "Ref": "ScheduleLambdaAccount",
+ },
+ ],
+ },
"ISSUES_TOPIC_ARN": {
"Ref": "InstanceSchedulerSnsTopic",
},
@@ -1339,6 +1527,24 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"SCHEDULER_FREQUENCY": {
"Ref": "SchedulerFrequency",
},
+ "SCHEDULER_ROLE_NAME": {
+ "Fn::FindInMap": [
+ "mappings",
+ "SchedulerRole",
+ "Name",
+ ],
+ },
+ "SCHEDULE_REGIONS": {
+ "Fn::Join": [
+ ",",
+ {
+ "Ref": "Regions",
+ },
+ ],
+ },
+ "SCHEDULE_TAG_KEY": {
+ "Ref": "TagName",
+ },
"SEND_METRICS": {
"Fn::FindInMap": [
"mappings",
@@ -1359,6 +1565,7 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"MetricsSolutionId",
],
},
+ "SOLUTION_VERSION": "v1.5.0",
"STACK_ID": {
"Ref": "AWS::StackId",
},
@@ -1366,11 +1573,14 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"Ref": "AWS::StackName",
},
"START_EC2_BATCH_SIZE": "5",
+ "START_TAGS": {
+ "Ref": "StartedTags",
+ },
"STATE_TABLE": {
"Ref": "StateTable",
},
- "TAG_NAME": {
- "Ref": "TagName",
+ "STOP_TAGS": {
+ "Ref": "StoppedTags",
},
"TRACE": {
"Fn::FindInMap": [
@@ -1381,18 +1591,6 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
},
],
},
- "USER_AGENT": {
- "Fn::Join": [
- "",
- [
- "InstanceScheduler-",
- {
- "Ref": "AWS::StackName",
- },
- "-v1.5.0",
- ],
- ],
- },
"USER_AGENT_EXTRA": "AwsSolution/SO0030/v1.5.0",
"UUID_KEY": {
"Fn::FindInMap": [
@@ -1424,7 +1622,7 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"Arn",
],
},
- "Runtime": "python3.9",
+ "Runtime": "python3.10",
"Timeout": 300,
"TracingConfig": {
"Mode": "Active",
@@ -1485,9 +1683,6 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"aws_partition": {
"Fn::Sub": "\${AWS::Partition}",
},
- "config_table": {
- "Ref": "ConfigTable",
- },
"create_rds_snapshot": {
"Fn::FindInMap": [
"mappings",
@@ -1500,7 +1695,7 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
"default_timezone": {
"Ref": "DefaultTimezone",
},
- "enable_SSM_maintenance_windows": {
+ "enable_ssm_maintenance_windows": {
"Fn::FindInMap": [
"mappings",
"TrueFalse",
@@ -1877,7 +2072,7 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
],
"Effect": "Allow",
"Resource": {
- "Fn::Sub": "arn:\${AWS::Partition}:ssm:\${AWS::Region}:\${AWS::AccountId}:parameter/Solutions/aws-instance-scheduler/UUID/*",
+ "Fn::Sub": "arn:\${AWS::Partition}:ssm:\${AWS::Region}:\${AWS::AccountId}:parameter/Solutions/instance-scheduler-on-aws/UUID/*",
},
},
],
@@ -1922,6 +2117,7 @@ exports[`AwsInstanceSchedulerStack snapshot test 1`] = `
],
},
"Id": "Target0",
+ "Input": "{"scheduled_action":"run_orchestrator"}",
},
],
},
diff --git a/source/infrastructure/instance-scheduler/tests/aws-instance-scheduler-remote-stack.test.ts b/source/instance-scheduler/tests/instance-scheduler-remote-stack.test.ts
similarity index 71%
rename from source/infrastructure/instance-scheduler/tests/aws-instance-scheduler-remote-stack.test.ts
rename to source/instance-scheduler/tests/instance-scheduler-remote-stack.test.ts
index ed9a5040..a9134892 100644
--- a/source/infrastructure/instance-scheduler/tests/aws-instance-scheduler-remote-stack.test.ts
+++ b/source/instance-scheduler/tests/instance-scheduler-remote-stack.test.ts
@@ -1,12 +1,8 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
-
import { createSpokeStack } from "./instance-scheduler-stack-factory";
import { Template } from "aws-cdk-lib/assertions";
-/*
- * SnapShot Testing for the AwsInstanceSchedulerStack.
- */
-test("AwsInstanceSchedulerStack snapshot test", () => {
+test("InstanceSchedulerRemoteStack snapshot test", () => {
expect(Template.fromStack(createSpokeStack())).toMatchSnapshot();
});
diff --git a/source/instance-scheduler/tests/instance-scheduler-stack-factory.ts b/source/instance-scheduler/tests/instance-scheduler-stack-factory.ts
new file mode 100644
index 00000000..0980badc
--- /dev/null
+++ b/source/instance-scheduler/tests/instance-scheduler-stack-factory.ts
@@ -0,0 +1,39 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import * as instanceSchedulerHubStack from "../lib/instance-scheduler-stack";
+import * as instanceSchedulerSpokeStack from "../lib/remote-stack";
+import * as cdk from "aws-cdk-lib";
+import { DefaultStackSynthesizer } from "aws-cdk-lib";
+
+export function createHubStack(): cdk.Stack {
+ const app = new cdk.App();
+ const envEU = { account: "111111111111", region: "eu-west-1" };
+ const stack = new instanceSchedulerHubStack.InstanceSchedulerStack(app, "stack", {
+ env: envEU,
+ description: "",
+ solutionId: "SO0030",
+ solutionName: "instance-scheduler-on-aws",
+ solutionVersion: "v1.5.0",
+ appregApplicationName: "AWS-Solutions",
+ appregSolutionName: "instance-scheduler-on-aws",
+ synthesizer: new DefaultStackSynthesizer({ generateBootstrapVersionRule: false }),
+ });
+ return stack;
+}
+
+export function createSpokeStack(): cdk.Stack {
+ const envEU = { account: "111111111111", region: "eu-west-1" };
+ const app = new cdk.App();
+ const stack = new instanceSchedulerSpokeStack.InstanceSchedulerRemoteStack(app, "stack", {
+ env: envEU,
+ description: "",
+ solutionId: "SO0030",
+ solutionName: "instance-scheduler-on-aws",
+ solutionVersion: "v1.5.0",
+ appregApplicationName: "AWS-Solutions",
+ appregSolutionName: "instance-scheduler-on-aws",
+ synthesizer: new DefaultStackSynthesizer({ generateBootstrapVersionRule: false }),
+ });
+ return stack;
+}
diff --git a/source/instance-scheduler/tests/instance-scheduler-stack.test.ts b/source/instance-scheduler/tests/instance-scheduler-stack.test.ts
new file mode 100644
index 00000000..234d53cf
--- /dev/null
+++ b/source/instance-scheduler/tests/instance-scheduler-stack.test.ts
@@ -0,0 +1,20 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+import { Template } from "aws-cdk-lib/assertions";
+import { createHubStack } from "./instance-scheduler-stack-factory";
+
+test("InstanceSchedulerStack snapshot test", () => {
+ const hubStackJson = Template.fromStack(createHubStack()).toJSON();
+ hubStackJson.Resources.Main.Properties.Code = "Omitted to remove snapshot dependency on code hash";
+ expect(hubStackJson).toMatchSnapshot();
+});
+
+test("Hub stack has expected defaults for started and stopped tags", () => {
+ const hubStackTemplate = Template.fromStack(createHubStack());
+ expect(hubStackTemplate.findParameters("StartedTags")["StartedTags"]["Default"]).toBe(
+ "InstanceScheduler-LastAction=Started By {scheduler} {year}/{month}/{day} {hour}:{minute}{timezone}, ",
+ );
+ expect(hubStackTemplate.findParameters("StoppedTags")["StoppedTags"]["Default"]).toBe(
+ "InstanceScheduler-LastAction=Stopped By {scheduler} {year}/{month}/{day} {hour}:{minute}{timezone}, ",
+ );
+});
diff --git a/source/infrastructure/instance-scheduler/tests/lib/core-scheduler.test.ts b/source/instance-scheduler/tests/lib/core-scheduler.test.ts
similarity index 96%
rename from source/infrastructure/instance-scheduler/tests/lib/core-scheduler.test.ts
rename to source/instance-scheduler/tests/lib/core-scheduler.test.ts
index 1b9b28a7..1e4787df 100644
--- a/source/infrastructure/instance-scheduler/tests/lib/core-scheduler.test.ts
+++ b/source/instance-scheduler/tests/lib/core-scheduler.test.ts
@@ -12,7 +12,7 @@ describe("core scheduler", function () {
const role = new Role(stack, "Role", {
assumedBy: new CompositePrincipal(
new ServicePrincipal("events.amazonaws.com"),
- new ServicePrincipal("lambda.amazonaws.com")
+ new ServicePrincipal("lambda.amazonaws.com"),
),
});
@@ -38,7 +38,7 @@ describe("core scheduler", function () {
AttributeName: key,
KeyType: "HASH",
},
- ])
+ ]),
);
expect(table.Properties.AttributeDefinitions).toEqual(
expect.arrayContaining([
@@ -46,7 +46,7 @@ describe("core scheduler", function () {
AttributeName: key,
AttributeType: "S",
},
- ])
+ ]),
);
});
@@ -59,7 +59,7 @@ describe("core scheduler", function () {
AttributeName: key,
KeyType: "RANGE",
},
- ])
+ ]),
);
expect(table.Properties.AttributeDefinitions).toEqual(
expect.arrayContaining([
@@ -67,7 +67,7 @@ describe("core scheduler", function () {
AttributeName: key,
AttributeType: "S",
},
- ])
+ ]),
);
});
@@ -81,7 +81,7 @@ describe("core scheduler", function () {
});
});
- it.skip("is encrypted with KMS key", function () {
+ it("is encrypted with KMS key", function () {
const keys = template.findResources("AWS::KMS::Key");
const keyIds = Object.getOwnPropertyNames(keys);
expect(keyIds).toHaveLength(1);
@@ -112,7 +112,7 @@ describe("core scheduler", function () {
AttributeName: key,
KeyType: "HASH",
},
- ])
+ ]),
);
expect(table.Properties.AttributeDefinitions).toEqual(
expect.arrayContaining([
@@ -120,7 +120,7 @@ describe("core scheduler", function () {
AttributeName: key,
AttributeType: "S",
},
- ])
+ ]),
);
});
@@ -133,7 +133,7 @@ describe("core scheduler", function () {
AttributeName: key,
KeyType: "RANGE",
},
- ])
+ ]),
);
expect(table.Properties.AttributeDefinitions).toEqual(
expect.arrayContaining([
@@ -141,7 +141,7 @@ describe("core scheduler", function () {
AttributeName: key,
AttributeType: "S",
},
- ])
+ ]),
);
});
@@ -186,7 +186,7 @@ describe("core scheduler", function () {
AttributeName: key,
KeyType: "HASH",
},
- ])
+ ]),
);
expect(table.Properties.AttributeDefinitions).toEqual(
expect.arrayContaining([
@@ -194,7 +194,7 @@ describe("core scheduler", function () {
AttributeName: key,
AttributeType: "S",
},
- ])
+ ]),
);
});
@@ -207,7 +207,7 @@ describe("core scheduler", function () {
AttributeName: key,
KeyType: "RANGE",
},
- ])
+ ]),
);
expect(table.Properties.AttributeDefinitions).toEqual(
expect.arrayContaining([
@@ -215,7 +215,7 @@ describe("core scheduler", function () {
AttributeName: key,
AttributeType: "S",
},
- ])
+ ]),
);
});
@@ -229,7 +229,7 @@ describe("core scheduler", function () {
});
});
- it.skip("is encrypted with KMS key", function () {
+ it("is encrypted with KMS key", function () {
const keys = template.findResources("AWS::KMS::Key");
const keyIds = Object.getOwnPropertyNames(keys);
expect(keyIds).toHaveLength(1);
@@ -259,7 +259,7 @@ describe("core scheduler", function () {
expect(env).toEqual(
expect.objectContaining({
STATE_TABLE: { Ref: stateTableLogicalId },
- })
+ }),
);
});
@@ -267,7 +267,7 @@ describe("core scheduler", function () {
expect(env).toEqual(
expect.objectContaining({
CONFIG_TABLE: { Ref: configTableLogicalId },
- })
+ }),
);
});
@@ -275,7 +275,7 @@ describe("core scheduler", function () {
expect(env).toEqual(
expect.objectContaining({
MAINTENANCE_WINDOW_TABLE: { Ref: maintenanceWindowTableLogicalId },
- })
+ }),
);
});
});
@@ -294,7 +294,7 @@ describe("core scheduler", function () {
Effect: "Allow",
Principal: { Service: "lambda.amazonaws.com" },
},
- ])
+ ]),
);
});
@@ -306,7 +306,7 @@ describe("core scheduler", function () {
Effect: "Allow",
Principal: { Service: "events.amazonaws.com" },
},
- ])
+ ]),
);
});
});
@@ -329,7 +329,7 @@ describe("core scheduler", function () {
Effect: "Allow",
Resource: "*",
},
- ])
+ ]),
);
});
@@ -358,7 +358,7 @@ describe("core scheduler", function () {
},
]),
},
- ])
+ ]),
);
});
@@ -381,7 +381,7 @@ describe("core scheduler", function () {
},
]),
},
- ])
+ ]),
);
});
@@ -404,7 +404,7 @@ describe("core scheduler", function () {
},
]),
},
- ])
+ ]),
);
});
});
diff --git a/source/infrastructure/pipeline/e2e-tests/basic-ec2-start-stop.test.resources.ts b/source/pipeline/e2e-tests/basic-ec2-start-stop.test.resources.ts
similarity index 88%
rename from source/infrastructure/pipeline/e2e-tests/basic-ec2-start-stop.test.resources.ts
rename to source/pipeline/e2e-tests/basic-ec2-start-stop.test.resources.ts
index 40e2c6d6..4a623b1f 100644
--- a/source/infrastructure/pipeline/e2e-tests/basic-ec2-start-stop.test.resources.ts
+++ b/source/pipeline/e2e-tests/basic-ec2-start-stop.test.resources.ts
@@ -21,7 +21,7 @@ export class EC2StartStopTestResources implements TestResourceProvider {
createTestResources(scope: Construct) {
const testInstance = new ec2.Instance(scope, "basic-start-stop-instance", {
instanceType: ec2.InstanceType.of(ec2.InstanceClass.T2, ec2.InstanceSize.MICRO),
- machineImage: ec2.MachineImage.latestAmazonLinux(),
+ machineImage: ec2.MachineImage.latestAmazonLinux2(),
vpc: defaultTestVPC(scope),
});
@@ -32,6 +32,10 @@ export class EC2StartStopTestResources implements TestResourceProvider {
});
NagSuppressions.addResourceSuppressions(testInstance, [
+ {
+ id: "AwsSolutions-EC26",
+ reason: "This is an automated test instance without any need for encrypted EBS volumes",
+ },
{
id: "AwsSolutions-EC28",
reason: "This is a test instance that only ever needs to be started/stopped (work workloads)",
diff --git a/source/infrastructure/pipeline/e2e-tests/basic-ec2-start-stop.test.ts b/source/pipeline/e2e-tests/basic-ec2-start-stop.test.ts
similarity index 87%
rename from source/infrastructure/pipeline/e2e-tests/basic-ec2-start-stop.test.ts
rename to source/pipeline/e2e-tests/basic-ec2-start-stop.test.ts
index 7b15844d..0240695c 100644
--- a/source/infrastructure/pipeline/e2e-tests/basic-ec2-start-stop.test.ts
+++ b/source/pipeline/e2e-tests/basic-ec2-start-stop.test.ts
@@ -6,7 +6,7 @@ import * as ec2 from "@aws-sdk/client-ec2";
import { resourceParams } from "./basic-ec2-start-stop.test.resources";
import { delayMinutes } from "./index";
import { getInstanceState } from "./utils/ec2-test-utils";
-import { createSchedule, currentTimePlus } from "./utils/schedule-test-utils";
+import { createSchedule, currentTimePlus, toTimeStr } from "./utils/schedule-test-utils";
const ec2Client = new ec2.EC2Client({});
const instanceId = resourceParams.ec2InstanceId;
@@ -19,7 +19,7 @@ test("basic ec2 start-stop schedule", async () => {
await ec2Client.send(
new ec2.StopInstancesCommand({
InstanceIds: [instanceId],
- })
+ }),
);
//confirm stopped
@@ -34,8 +34,8 @@ test("basic ec2 start-stop schedule", async () => {
{
name: "ec2-start-stop-period",
description: `testing period`,
- begintime: currentTimePlus(3),
- endtime: currentTimePlus(7),
+ begintime: toTimeStr(currentTimePlus(3)),
+ endtime: toTimeStr(currentTimePlus(7)),
},
],
});
diff --git a/source/infrastructure/pipeline/e2e-tests/basic-rds-start-stop.test.resources.ts b/source/pipeline/e2e-tests/basic-rds-start-stop.test.resources.ts
similarity index 99%
rename from source/infrastructure/pipeline/e2e-tests/basic-rds-start-stop.test.resources.ts
rename to source/pipeline/e2e-tests/basic-rds-start-stop.test.resources.ts
index 5eb008ea..1dd80edc 100644
--- a/source/infrastructure/pipeline/e2e-tests/basic-rds-start-stop.test.resources.ts
+++ b/source/pipeline/e2e-tests/basic-rds-start-stop.test.resources.ts
@@ -61,7 +61,7 @@ export class BasicRdsStartStopTestResources implements TestResourceProvider {
reason: "Short-lived test instance with no need for secrets rotation",
},
],
- true
+ true,
);
return {
diff --git a/source/infrastructure/pipeline/e2e-tests/basic-rds-start-stop.test.ts b/source/pipeline/e2e-tests/basic-rds-start-stop.test.ts
similarity index 89%
rename from source/infrastructure/pipeline/e2e-tests/basic-rds-start-stop.test.ts
rename to source/pipeline/e2e-tests/basic-rds-start-stop.test.ts
index 614c16c5..cc8fdaac 100644
--- a/source/infrastructure/pipeline/e2e-tests/basic-rds-start-stop.test.ts
+++ b/source/pipeline/e2e-tests/basic-rds-start-stop.test.ts
@@ -5,7 +5,7 @@ import * as rds from "@aws-sdk/client-rds";
import { resourceParams } from "./basic-rds-start-stop.test.resources";
import { delayMinutes } from "./index";
import { getInstanceState } from "./utils/rds-test-utils";
-import { createSchedule, currentTimePlus } from "./utils/schedule-test-utils";
+import { createSchedule, currentTimePlus, toTimeStr } from "./utils/schedule-test-utils";
const rdsClient = new rds.RDSClient({});
@@ -13,7 +13,7 @@ test("rdsInstanceAccessible", async () => {
const fetchResult = await rdsClient.send(
new rds.DescribeDBInstancesCommand({
DBInstanceIdentifier: resourceParams.rdsInstanceId,
- })
+ }),
);
expect(fetchResult.DBInstances?.[0]).not.toBeUndefined();
@@ -26,7 +26,7 @@ test("basic rds start-stop schedule", async () => {
await rdsClient.send(
new rds.StopDBInstanceCommand({
DBInstanceIdentifier: resourceParams.rdsInstanceId,
- })
+ }),
);
await delayMinutes(5);
}
@@ -39,8 +39,8 @@ test("basic rds start-stop schedule", async () => {
{
name: "rds-start-stop-period",
description: `testing period`,
- begintime: currentTimePlus(3),
- endtime: currentTimePlus(7),
+ begintime: toTimeStr(currentTimePlus(3)),
+ endtime: toTimeStr(currentTimePlus(7)),
},
],
});
diff --git a/source/pipeline/e2e-tests/ec2-maintenance-window.test.resources.ts b/source/pipeline/e2e-tests/ec2-maintenance-window.test.resources.ts
new file mode 100644
index 00000000..d9cfd926
--- /dev/null
+++ b/source/pipeline/e2e-tests/ec2-maintenance-window.test.resources.ts
@@ -0,0 +1,53 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import * as ec2 from "aws-cdk-lib/aws-ec2";
+import * as cdk from "aws-cdk-lib";
+
+import { Construct } from "constructs";
+import { NagSuppressions } from "cdk-nag";
+import { TestResourceProvider } from "./index";
+import { defaultTestVPC } from "./utils/vpc-utils";
+
+const envKeys = {
+ ec2InstanceId: "ec2_maintenance_window_start_instance_id",
+};
+export const resourceParams = {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ ec2InstanceId: process.env[envKeys.ec2InstanceId]!,
+ maintWindowTestScheduleName: "ec2_maintenance_window_test_schedule",
+};
+export class EC2MaintenanceWindowStartTestResource implements TestResourceProvider {
+ createTestResources(scope: Construct) {
+ const testInstance = new ec2.Instance(scope, "maint_window_start_instance", {
+ instanceType: ec2.InstanceType.of(ec2.InstanceClass.T2, ec2.InstanceSize.MICRO),
+ machineImage: ec2.MachineImage.latestAmazonLinux2(),
+ vpc: defaultTestVPC(scope),
+ });
+
+ cdk.Tags.of(testInstance).add("Schedule", resourceParams.maintWindowTestScheduleName);
+
+ const startStopOut = new cdk.CfnOutput(scope, envKeys.ec2InstanceId, {
+ value: testInstance.instanceId,
+ });
+
+ NagSuppressions.addResourceSuppressions(testInstance, [
+ {
+ id: "AwsSolutions-EC26",
+ reason: "This is an automated test instance without any need for encrypted EBS volumes",
+ },
+ {
+ id: "AwsSolutions-EC28",
+ reason: "This is a test instance that only ever needs to be started/stopped (work workloads)",
+ },
+ {
+ id: "AwsSolutions-EC29",
+ reason: "This is an automated test instance without any need for termination protection",
+ },
+ ]);
+
+ return {
+ [envKeys.ec2InstanceId]: startStopOut,
+ };
+ }
+}
diff --git a/source/pipeline/e2e-tests/ec2-maintenance-window.test.ts b/source/pipeline/e2e-tests/ec2-maintenance-window.test.ts
new file mode 100644
index 00000000..dc9adea8
--- /dev/null
+++ b/source/pipeline/e2e-tests/ec2-maintenance-window.test.ts
@@ -0,0 +1,69 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import * as ssm from "@aws-sdk/client-ssm";
+import { CreateMaintenanceWindowCommand, DeleteMaintenanceWindowCommand } from "@aws-sdk/client-ssm";
+import { createSchedule, currentTimePlus } from "./utils/schedule-test-utils";
+import * as ec2 from "@aws-sdk/client-ec2";
+import { resourceParams } from "./ec2-maintenance-window.test.resources";
+import { delayMinutes } from "./index";
+import { getInstanceState } from "./utils/ec2-test-utils";
+
+const ssmClient = new ssm.SSMClient({});
+const ec2Client = new ec2.EC2Client({});
+const instanceId = resourceParams.ec2InstanceId;
+
+function getCronStrForTime(time: Date) {
+ return `cron(0 ${time.getUTCMinutes()} ${time.getUTCHours()} ? * *)`;
+}
+test("maintenance window start behavior", async () => {
+ //stop instance
+ await ec2Client.send(
+ new ec2.StopInstancesCommand({
+ InstanceIds: [instanceId],
+ }),
+ );
+
+ //confirm stopped
+ await delayMinutes(1);
+ expect(await getInstanceState(ec2Client, instanceId)).toBe(ec2.InstanceStateName.stopped);
+
+ //create maintenance window
+ let window_id: string | undefined;
+ await ssmClient
+ .send(
+ new CreateMaintenanceWindowCommand({
+ Name: "test-window",
+ Description: "e2e test window",
+ Schedule: getCronStrForTime(currentTimePlus(12)),
+ ScheduleTimezone: "UTC",
+ Duration: 1,
+ Cutoff: 0,
+ AllowUnassociatedTargets: false,
+ Tags: [],
+ }),
+ )
+ .then((response) => {
+ window_id = response.WindowId;
+ });
+
+ try {
+ //create schedule
+ await createSchedule({
+ name: resourceParams.maintWindowTestScheduleName,
+ description: `testing schedule`,
+ use_maintenance_window: true,
+ ssm_maintenance_window: "test-window",
+ });
+
+ //confirm instance started in anticipation of upcoming maintenance window
+ await delayMinutes(5);
+ expect(await getInstanceState(ec2Client, instanceId)).toBe(ec2.InstanceStateName.running);
+ } finally {
+ await ssmClient.send(
+ new DeleteMaintenanceWindowCommand({
+ WindowId: window_id,
+ }),
+ );
+ }
+}, 900_000);
diff --git a/source/infrastructure/pipeline/e2e-tests/index.ts b/source/pipeline/e2e-tests/index.ts
similarity index 85%
rename from source/infrastructure/pipeline/e2e-tests/index.ts
rename to source/pipeline/e2e-tests/index.ts
index 0bf3fa35..c75335d0 100644
--- a/source/infrastructure/pipeline/e2e-tests/index.ts
+++ b/source/pipeline/e2e-tests/index.ts
@@ -5,6 +5,7 @@ import { Construct } from "constructs";
import { EC2StartStopTestResources } from "./basic-ec2-start-stop.test.resources";
import { CfnOutput } from "aws-cdk-lib";
import { BasicRdsStartStopTestResources } from "./basic-rds-start-stop.test.resources";
+import { EC2MaintenanceWindowStartTestResource } from "./ec2-maintenance-window.test.resources";
export interface TestResourceProvider {
createTestResources(scope: Construct): Record;
@@ -13,6 +14,7 @@ export interface TestResourceProvider {
export const testResourceProviders: TestResourceProvider[] = [
new EC2StartStopTestResources(),
new BasicRdsStartStopTestResources(),
+ new EC2MaintenanceWindowStartTestResource(),
];
export const delaySeconds = (seconds: number) => new Promise((res) => setTimeout(res, seconds * 1000));
diff --git a/source/infrastructure/pipeline/e2e-tests/utils/ec2-test-utils.ts b/source/pipeline/e2e-tests/utils/ec2-test-utils.ts
similarity index 98%
rename from source/infrastructure/pipeline/e2e-tests/utils/ec2-test-utils.ts
rename to source/pipeline/e2e-tests/utils/ec2-test-utils.ts
index 78e6734c..4b24e99f 100644
--- a/source/infrastructure/pipeline/e2e-tests/utils/ec2-test-utils.ts
+++ b/source/pipeline/e2e-tests/utils/ec2-test-utils.ts
@@ -8,7 +8,7 @@ export async function getInstanceState(client: ec2.EC2Client, instanceId: string
new ec2.DescribeInstanceStatusCommand({
InstanceIds: [instanceId],
IncludeAllInstances: true,
- })
+ }),
);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
diff --git a/source/infrastructure/pipeline/e2e-tests/utils/hub-stack-utils.ts b/source/pipeline/e2e-tests/utils/hub-stack-utils.ts
similarity index 81%
rename from source/infrastructure/pipeline/e2e-tests/utils/hub-stack-utils.ts
rename to source/pipeline/e2e-tests/utils/hub-stack-utils.ts
index a81aa26b..46228cc1 100644
--- a/source/infrastructure/pipeline/e2e-tests/utils/hub-stack-utils.ts
+++ b/source/pipeline/e2e-tests/utils/hub-stack-utils.ts
@@ -1,7 +1,7 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
-import { AwsInstanceSchedulerStack } from "../../../instance-scheduler/lib/aws-instance-scheduler-stack";
+import { InstanceSchedulerStack } from "../../../instance-scheduler/lib/instance-scheduler-stack";
import { CfnOutput } from "aws-cdk-lib";
const envKeys = {
@@ -19,7 +19,7 @@ export const hubStackParams = {
schedulerRoleArn: process.env[envKeys.SCHEDULER_ROLE_ARN]!,
};
-export function extractOutputsFrom(hubStack: AwsInstanceSchedulerStack): Record {
+export function extractOutputsFrom(hubStack: InstanceSchedulerStack): Record {
return {
[envKeys.CONFIG_TABLE]: hubStack.configurationTableOutput,
[envKeys.ISSUE_SNS_TOPIC_ARN]: hubStack.issueSnsTopicArn,
diff --git a/source/infrastructure/pipeline/e2e-tests/utils/rds-test-utils.ts b/source/pipeline/e2e-tests/utils/rds-test-utils.ts
similarity index 99%
rename from source/infrastructure/pipeline/e2e-tests/utils/rds-test-utils.ts
rename to source/pipeline/e2e-tests/utils/rds-test-utils.ts
index 1fe46ebb..5d2194ac 100644
--- a/source/infrastructure/pipeline/e2e-tests/utils/rds-test-utils.ts
+++ b/source/pipeline/e2e-tests/utils/rds-test-utils.ts
@@ -12,7 +12,7 @@ export async function getInstanceState(client: rds.RDSClient, instanceId: string
const result = await client.send(
new rds.DescribeDBInstancesCommand({
DBInstanceIdentifier: instanceId,
- })
+ }),
);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
diff --git a/source/infrastructure/pipeline/e2e-tests/utils/schedule-test-utils.ts b/source/pipeline/e2e-tests/utils/schedule-test-utils.ts
similarity index 63%
rename from source/infrastructure/pipeline/e2e-tests/utils/schedule-test-utils.ts
rename to source/pipeline/e2e-tests/utils/schedule-test-utils.ts
index 8e1cd7f7..01da9c67 100644
--- a/source/infrastructure/pipeline/e2e-tests/utils/schedule-test-utils.ts
+++ b/source/pipeline/e2e-tests/utils/schedule-test-utils.ts
@@ -3,6 +3,7 @@
import * as dynamodb from "@aws-sdk/client-dynamodb";
import { hubStackParams } from "./hub-stack-utils";
+import { AttributeValue } from "@aws-sdk/client-dynamodb";
const configTableName = hubStackParams.configTableArn.substring(hubStackParams.configTableArn.lastIndexOf("/") + 1);
export interface Period {
@@ -15,7 +16,9 @@ export interface Period {
export interface Schedule {
name: string;
description: string;
- periods: Period[];
+ periods?: Period[];
+ use_maintenance_window?: boolean;
+ ssm_maintenance_window?: string;
}
export async function createSchedule(schedule: Schedule) {
const dynamoClient = new dynamodb.DynamoDBClient({});
@@ -25,7 +28,7 @@ export async function createSchedule(schedule: Schedule) {
RequestItems: {
[configTableName]: scheduleToBatchedPutRequests(schedule),
},
- })
+ }),
);
} finally {
dynamoClient.destroy();
@@ -35,9 +38,13 @@ export async function createSchedule(schedule: Schedule) {
/**
* @return period-compatible time string that is n minutes in the future in UTC
*/
-export function currentTimePlus(minutes: number): string {
+export function currentTimePlus(minutes: number): Date {
const targetTime = new Date();
targetTime.setTime(targetTime.getTime() + minutesToMillis(minutes));
+ return targetTime;
+}
+
+export function toTimeStr(targetTime: Date): string {
return `${targetTime.getUTCHours()}:${targetTime.getUTCMinutes()}`;
}
@@ -46,18 +53,27 @@ function minutesToMillis(minutes: number) {
}
function scheduleToBatchedPutRequests(schedule: Schedule): dynamodb.WriteRequest[] {
- return [...schedule.periods.map((period) => putRequestForPeriod(period)), putRequestForSchedule(schedule)];
+ const requests: dynamodb.WriteRequest[] = [];
+ if (schedule.periods) requests.push(...schedule.periods.map((period) => putRequestForPeriod(period)));
+ requests.push(putRequestForSchedule(schedule));
+
+ return requests;
}
function putRequestForSchedule(schedule: Schedule): dynamodb.WriteRequest {
+ const item: { [key: string]: AttributeValue } = {
+ type: { S: "schedule" },
+ name: { S: schedule.name },
+ description: { S: schedule.description },
+ };
+
+ if (schedule.periods) item.periods = { SS: schedule.periods.map((period) => period.name) };
+ if (schedule.use_maintenance_window) item.use_maintenance_window = { BOOL: schedule.use_maintenance_window };
+ if (schedule.ssm_maintenance_window) item.ssm_maintenance_window = { S: schedule.ssm_maintenance_window };
+
return {
PutRequest: {
- Item: {
- type: { S: "schedule" },
- name: { S: schedule.name },
- description: { S: schedule.description },
- periods: { SS: schedule.periods.map((period) => period.name) },
- },
+ Item: item,
},
};
}
diff --git a/source/infrastructure/pipeline/e2e-tests/utils/vpc-utils.ts b/source/pipeline/e2e-tests/utils/vpc-utils.ts
similarity index 100%
rename from source/infrastructure/pipeline/e2e-tests/utils/vpc-utils.ts
rename to source/pipeline/e2e-tests/utils/vpc-utils.ts
diff --git a/source/infrastructure/pipeline/jest.config.ts b/source/pipeline/jest.config.ts
similarity index 87%
rename from source/infrastructure/pipeline/jest.config.ts
rename to source/pipeline/jest.config.ts
index 57d9984d..1bb68b71 100644
--- a/source/infrastructure/pipeline/jest.config.ts
+++ b/source/pipeline/jest.config.ts
@@ -11,7 +11,7 @@ module.exports = {
[
"jest-junit",
{
- outputDirectory: "../../deployment/test-reports",
+ outputDirectory: "deployment/test-reports",
outputName: "e2e-test-report.xml",
},
],
diff --git a/source/pipeline/lib/code-commit-source.ts b/source/pipeline/lib/code-commit-source.ts
new file mode 100644
index 00000000..04de7ca5
--- /dev/null
+++ b/source/pipeline/lib/code-commit-source.ts
@@ -0,0 +1,15 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import { Construct } from "constructs";
+import { PipelineBootstrapStack, tokenFor } from "./pipeline-bootstrap-stack";
+import * as codecommit from "aws-cdk-lib/aws-codecommit";
+import * as pipelines from "aws-cdk-lib/pipelines";
+
+export function buildCodeCommitSource(scope: Construct) {
+ const repoName = tokenFor(scope, PipelineBootstrapStack.ssmParamKeys.repoName);
+ const branchName = tokenFor(scope, PipelineBootstrapStack.ssmParamKeys.repoBranch);
+ const repo = codecommit.Repository.fromRepositoryName(scope, "instanceSchedulerRepo", repoName);
+
+ return pipelines.CodePipelineSource.codeCommit(repo, branchName);
+}
diff --git a/source/infrastructure/pipeline/lib/code-star-source.ts b/source/pipeline/lib/code-star-source.ts
similarity index 69%
rename from source/infrastructure/pipeline/lib/code-star-source.ts
rename to source/pipeline/lib/code-star-source.ts
index 411a4201..96c66ff3 100644
--- a/source/infrastructure/pipeline/lib/code-star-source.ts
+++ b/source/pipeline/lib/code-star-source.ts
@@ -3,6 +3,8 @@
import * as cp_actions from "aws-cdk-lib/aws-codepipeline-actions";
import { CodePipelineSource, FileSet } from "aws-cdk-lib/pipelines";
import { Artifact } from "aws-cdk-lib/aws-codepipeline";
+import { PipelineBootstrapStack, tokenFor } from "./pipeline-bootstrap-stack";
+import { Construct } from "constructs";
class CodeStarSource extends CodePipelineSource {
// We need another class here instead of using the factory .connection() because
@@ -18,7 +20,13 @@ class CodeStarSource extends CodePipelineSource {
private readonly connectionArn: string;
- constructor(name: string, connectionArn: string, owner: string, repo: string, readonly branch: string) {
+ constructor(
+ name: string,
+ connectionArn: string,
+ owner: string,
+ repo: string,
+ readonly branch: string,
+ ) {
super(name);
this.owner = owner;
this.repo = repo;
@@ -40,4 +48,14 @@ class CodeStarSource extends CodePipelineSource {
}
}
+export function buildCodeStarSource(scope: Construct) {
+ return new CodeStarSource(
+ "CodeStarConnection",
+ tokenFor(scope, PipelineBootstrapStack.ssmParamKeys.codestarArn),
+ tokenFor(scope, PipelineBootstrapStack.ssmParamKeys.repoOwner),
+ tokenFor(scope, PipelineBootstrapStack.ssmParamKeys.repoName),
+ tokenFor(scope, PipelineBootstrapStack.ssmParamKeys.repoBranch),
+ );
+}
+
export default CodeStarSource;
diff --git a/source/infrastructure/pipeline/lib/e2e-test-stack.ts b/source/pipeline/lib/e2e-test-stack.ts
similarity index 100%
rename from source/infrastructure/pipeline/lib/e2e-test-stack.ts
rename to source/pipeline/lib/e2e-test-stack.ts
diff --git a/source/pipeline/lib/pipeline-bootstrap-stack.ts b/source/pipeline/lib/pipeline-bootstrap-stack.ts
new file mode 100644
index 00000000..d7376836
--- /dev/null
+++ b/source/pipeline/lib/pipeline-bootstrap-stack.ts
@@ -0,0 +1,94 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+import { CfnParameter, DefaultStackSynthesizer, Stack } from "aws-cdk-lib";
+import * as ssm from "aws-cdk-lib/aws-ssm";
+import { StringParameter } from "aws-cdk-lib/aws-ssm";
+import { Construct } from "constructs";
+
+export class PipelineBootstrapStack extends Stack {
+ static readonly ssmParamKeys = {
+ codestarArn: "/InstanceScheduler-build/connection/arn",
+ repoOwner: "/InstanceScheduler-build/connection/owner",
+ repoName: "/InstanceScheduler-build/connection/repo",
+ repoBranch: "/InstanceScheduler-build/connection/branch",
+ };
+
+ constructor(scope: Construct, construct_id: string) {
+ super(scope, construct_id, {
+ synthesizer: new DefaultStackSynthesizer({
+ generateBootstrapVersionRule: false,
+ }),
+ });
+
+ const ssmInputs = {
+ codestarArn: new CfnParameter(this, "CodestarArn", {
+ type: "String",
+ description: "CodeStar connection ARN (when sourcing from GitHub)",
+ default: "----",
+ }),
+ repoOwner: new CfnParameter(this, "RepoOwner", {
+ type: "String",
+ description: "GitHub repo owner (when sourcing from GitHub)",
+ default: "----",
+ }),
+ repoName: new CfnParameter(this, "RepoName", {
+ type: "String",
+ description: "repo name",
+ default: "----",
+ }),
+ repoBranch: new CfnParameter(this, "RepoBranch", {
+ type: "String",
+ description: "repo branch",
+ default: "----",
+ }),
+ };
+
+ const stack = Stack.of(this);
+ stack.templateOptions.metadata = {
+ "AWS::CloudFormation::Interface": {
+ ParameterGroups: [
+ {
+ Label: {
+ default: "Required",
+ },
+ Parameters: ["RepoName", "RepoBranch"],
+ },
+ {
+ Label: {
+ default: "GitHub-Only",
+ },
+ Parameters: ["RepoOwner", "CodestarArn"],
+ },
+ ],
+ },
+ };
+
+ new ssm.StringParameter(this, "code_arn", {
+ description: "CodeStar connection ARN (if using github as source)",
+ parameterName: PipelineBootstrapStack.ssmParamKeys.codestarArn,
+ stringValue: ssmInputs.codestarArn.valueAsString,
+ });
+
+ new ssm.StringParameter(this, "repo_owner", {
+ description: "Github repo owner (if using github as source)",
+ parameterName: PipelineBootstrapStack.ssmParamKeys.repoOwner,
+ stringValue: ssmInputs.repoOwner.valueAsString,
+ });
+
+ new ssm.StringParameter(this, "repo_name", {
+ description: "repo name",
+ parameterName: PipelineBootstrapStack.ssmParamKeys.repoName,
+ stringValue: ssmInputs.repoName.valueAsString,
+ });
+
+ new ssm.StringParameter(this, "repo_branch", {
+ description: "Github repo branch",
+ parameterName: PipelineBootstrapStack.ssmParamKeys.repoBranch,
+ stringValue: ssmInputs.repoBranch.valueAsString,
+ });
+ }
+}
+
+export function tokenFor(scope: Construct, ssmParamKey: string) {
+ return StringParameter.valueForStringParameter(scope, ssmParamKey);
+}
diff --git a/source/infrastructure/pipeline/lib/pipeline-stack.ts b/source/pipeline/lib/testing-pipeline-stack.ts
similarity index 70%
rename from source/infrastructure/pipeline/lib/pipeline-stack.ts
rename to source/pipeline/lib/testing-pipeline-stack.ts
index a1b957b1..9824647d 100644
--- a/source/infrastructure/pipeline/lib/pipeline-stack.ts
+++ b/source/pipeline/lib/testing-pipeline-stack.ts
@@ -3,11 +3,9 @@
import * as codebuild from "aws-cdk-lib/aws-codebuild";
import * as pipelines from "aws-cdk-lib/pipelines";
-import CodeStarSource from "./code-star-source";
import { Construct } from "constructs";
import { Stack, Stage } from "aws-cdk-lib";
-import { StringParameter } from "aws-cdk-lib/aws-ssm";
-import { AwsInstanceSchedulerStack } from "../../instance-scheduler/lib/aws-instance-scheduler-stack";
+import { InstanceSchedulerStack } from "../../instance-scheduler/lib/instance-scheduler-stack";
import { NagSuppressions } from "cdk-nag";
import { E2eTestStack } from "./e2e-test-stack";
import { Effect, PolicyStatement } from "aws-cdk-lib/aws-iam";
@@ -18,7 +16,11 @@ const END_TO_END_STAGE_NAME = "End-to-End-Tests";
const STACK_NAME = "InstanceScheduler";
const TEST_RESOURCES_STACK_NAME = "InstanceSchedulerE2ETestResources";
-class PipelineStack extends Stack {
+export interface SourceProvider {
+ getSource: (scope: Construct) => pipelines.IFileSetProducer;
+}
+
+export class TestingPipelineStack extends Stack {
/*
This stack establishes a pipeline that builds, deploys, and tests the solution
in a specified account. It also uses CodeStar connections to set up a webhook
@@ -37,12 +39,11 @@ class PipelineStack extends Stack {
Set up the connection by following the documentation at
https://docs.aws.amazon.com/dtconsole/latest/userguide/connections-create-github.html
*/
-
- constructor(scope: Construct, construct_id: string) {
+ constructor(scope: Construct, construct_id: string, sourceProvider: SourceProvider) {
super(scope, construct_id);
const pipeline = new pipelines.CodePipeline(this, "Pipeline", {
- synth: this.getSynthStep(),
+ synth: this.synthStep(sourceProvider.getSource(this)),
codeBuildDefaults: {
buildEnvironment: {
buildImage: codebuild.LinuxBuildImage.STANDARD_6_0,
@@ -54,12 +55,12 @@ class PipelineStack extends Stack {
const deployStage = new DeployStage(this, DEPLOY_STAGE_NAME);
pipeline.addStage(deployStage, {
- pre: [this.getUnitTestStep()],
+ pre: [this.unitTestStep()],
});
const e2eTestStage = new EndToEndTestStage(this, END_TO_END_STAGE_NAME);
pipeline.addStage(e2eTestStage, {
- post: [this.getEndToEndTestStep(deployStage.instanceSchedulerStack, e2eTestStage.e2eTestResourcesStack)],
+ post: [this.endToEndTestStep(deployStage.instanceSchedulerStack, e2eTestStage.e2eTestResourcesStack)],
});
//pipeline must be built before findings can be suppressed
@@ -83,33 +84,25 @@ class PipelineStack extends Stack {
]);
}
- get_connection() {
- return new CodeStarSource(
- "CodeStarConnection",
- StringParameter.valueForStringParameter(this, "/InstanceScheduler-build/connection/arn"),
- StringParameter.valueForStringParameter(this, "/InstanceScheduler-build/connection/owner"),
- StringParameter.valueForStringParameter(this, "/InstanceScheduler-build/connection/repo"),
- StringParameter.valueForStringParameter(this, "/InstanceScheduler-build/connection/branch")
- );
- }
-
- getSynthStep() {
+ synthStep(source: pipelines.IFileSetProducer) {
return new pipelines.CodeBuildStep("Synth", {
- input: this.get_connection(),
- installCommands: ["pip install tox"],
- commands: ["cd source/infrastructure", "npm ci", "cd pipeline", "npx cdk synth"],
- primaryOutputDirectory: "build/cdk.pipeline.out",
+ input: source,
+ installCommands: ["npm install --location=global npm@latest", "npm ci"],
+ commands: ["npm run synth"],
+ primaryOutputDirectory: "build/cdk.out",
});
}
- getUnitTestStep() {
+ unitTestStep() {
return new pipelines.CodeBuildStep("unitTests", {
- installCommands: ["pip install tox"],
- commands: [
- "tox -e cdk",
- "tox -e lambda -- --junitxml=../../deployment/test-reports/lambda-test-report.xml",
- "tox -e cli -- --junitxml=../../deployment/test-reports/cli-test-report.xml",
+ installCommands: [
+ "npm install --location=global npm@latest",
+ "pyenv install -s 3.8 3.9 3.11",
+ "pyenv global 3.11 3.9 3.8",
+ "python -m pip install -U pip setuptools tox",
+ "npm ci",
],
+ commands: ["npm run test:ci"],
partialBuildSpec: codebuild.BuildSpec.fromObject({
reports: {
cdk_test_reports: {
@@ -133,10 +126,10 @@ class PipelineStack extends Stack {
});
}
- getEndToEndTestStep(mainInstanceSchedulerStack: AwsInstanceSchedulerStack, testingResourcesStack: E2eTestStack) {
+ endToEndTestStep(mainInstanceSchedulerStack: InstanceSchedulerStack, testingResourcesStack: E2eTestStack) {
return new pipelines.CodeBuildStep("EndToEndTests", {
- installCommands: ["pip install tox"],
- commands: ["tox -e e2e"],
+ installCommands: ["npm install --location=global npm@latest", "npm ci"],
+ commands: ["npm run e2e-tests"],
envFromCfnOutputs: {
...testingResourcesStack.outputs,
...hubStackUtils.extractOutputsFrom(mainInstanceSchedulerStack),
@@ -166,18 +159,21 @@ class DeployStage extends Stage {
super(scope, construct_id);
}
- instanceSchedulerStack = new AwsInstanceSchedulerStack(this, STACK_NAME, {
- appregApplicationName: "",
- appregSolutionName: "",
- description: "",
- solutionId: "",
- solutionName: "",
- solutionVersion: "",
+ instanceSchedulerStack = new InstanceSchedulerStack(this, STACK_NAME, {
+ appregApplicationName: "AWS-Solutions",
+ appregSolutionName: "instance-scheduler-on-aws",
+ description: "test deployment from the InstanceScheduler e2e pipeline",
+ solutionId: "SO0030",
+ solutionName: "instance-scheduler-on-aws",
+ solutionVersion: "pipeline",
paramOverrides: {
schedulerFrequency: "1",
scheduledServices: "Both",
namespace: "e2etesting",
+ enableSSMMaintenanceWindows: "Yes",
+ trace: "Yes",
},
+ disableOpMetrics: true,
});
}
@@ -188,5 +184,3 @@ class EndToEndTestStage extends Stage {
e2eTestResourcesStack = new E2eTestStack(this, TEST_RESOURCES_STACK_NAME);
}
-
-export default PipelineStack;
diff --git a/tox.ini b/tox.ini
deleted file mode 100644
index 62ae716a..00000000
--- a/tox.ini
+++ /dev/null
@@ -1,85 +0,0 @@
-; Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
-; SPDX-License-Identifier: Apache-2.0
-
-[tox]
-env_list =
- lambda
- cdk
- cli
- eslint
- black
-minversion = 4.0.13
-package_root = source/app
-isolated_build = true
-
-[gh-actions]
-python =
- 3.9: lambda, cli, cdk
- 3.10: lambda, cli
- 3.11: lambda, cli
-
-[testenv:black]
-description = run black lint checks
-skip_install = true
-deps =
- black
-commands =
- black --check source
-
-[testenv:eslint]
-description = run eslint checks
-allowlist_externals =
- npm
- npx
-change_dir = source/infrastructure
-package = skip
-commands =
- npm install
- npx prettier --check '**/*.ts'
- npx eslint --max-warnings=0 .
-
-[testenv:lambda]
-description = run lambda unit tests
-allowlist_externals = poetry
-change_dir = source/app
-deps =
- poetry
-commands_pre =
- poetry install
-commands =
- poetry run pytest tests/ {posargs}
-
-[testenv:cli]
-description = run cli tests
-change_dir = source/cli
-allowlist_externals = poetry
-deps =
- poetry
-package = skip
-commands_pre =
- poetry install
-commands =
- poetry run pytest tests/ {posargs}
-
-
-[testenv:cdk]
-allowlist_externals = npm
-change_dir = source/infrastructure
-description = run CDK unit tests
-package = skip
-pass_env =
- USER
-commands =
- npm install
- npm run test -- {posargs}
-
-[testenv:e2e]
-allowlist_externals = npm
-change_dir = source/infrastructure
-description = run e2e tests
-package = skip
-pass_env =
- *
-commands =
- npm install
- npm run e2e-tests -- {posargs}
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 00000000..d7506b9e
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,49 @@
+// ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen".
+{
+ "compilerOptions": {
+ "rootDir": ".",
+ "outDir": "build/cdk.ts.dist",
+ "alwaysStrict": true,
+ "declaration": true,
+ "esModuleInterop": true,
+ "experimentalDecorators": true,
+ "inlineSourceMap": true,
+ "inlineSources": true,
+ "lib": [
+ "es2022",
+ "dom"
+ ],
+ "module": "CommonJS",
+ "noEmitOnError": true,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitAny": true,
+ "noImplicitReturns": true,
+ "noImplicitThis": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "resolveJsonModule": true,
+ "strict": true,
+ "strictNullChecks": true,
+ "strictPropertyInitialization": true,
+ "stripInternal": true,
+ "target": "ES2022",
+ "forceConsistentCasingInFileNames": true,
+ "noPropertyAccessFromIndexSignature": false,
+ "noUncheckedIndexedAccess": false,
+ "allowJs": false
+ },
+ "include": [
+ "source/**/*.ts",
+ "source/pipeline/**/*.ts",
+ "deployment/cdk-solution-helper/**/*.ts",
+ ".projenrc.ts",
+ "projenrc/**/*.ts"
+ ],
+ "exclude": [
+ "node_modules",
+ "build/cdk.out"
+ ],
+ "files": [
+ "global.d.ts"
+ ]
+}