diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b81c1a6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +data-container +node_modules diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c8d7720 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,20 @@ +FROM node:16-alpine +RUN apk add python3 libpcap libpcap-dev util-linux +COPY software/libnethogs.so.0.8.5-63-g68033bf /usr/local/lib +COPY software/nethogs-wrapper.py /usr/local/bin +RUN chmod +x /usr/local/bin/nethogs-wrapper.py +#ADD http://pegasus.isi.edu/montage/Montage_v3.3_patched_4.tar.gz / +#RUN tar zxvf Montage_v3.3_patched_4.tar.gz && \ +# make -C /Montage_v3.3_patched_4 && \ +# echo "export PATH=\$PATH:/Montage_v3.3_patched_4/bin" >> /etc/bash.bashrc && \ +# cd /Montage_v3.3_patched_4 && rm -rf Montage docs grid ../Montage_v3.3_patched_4.tar.gz + +ADD software/Montage.tar.gz / +ENV PATH $PATH:/Montage_v3.3_patched_4/bin +WORKDIR /usr/src/app +COPY package*.json ./ +RUN npm install +RUN npm install -g log4js +COPY . . + +CMD [ "npm", "start" ] \ No newline at end of file diff --git a/README.md b/README.md index 51b1fb5..044c47d 100644 --- a/README.md +++ b/README.md @@ -3,51 +3,59 @@ ## Dockerizing application Requirements: git, nodejs, docker -git clone https://github.com/hyperflow-wms/hyperflow-awsfargate-executor.git - -cd hyperflow-awsfargate-executor +Clone this repository npm install -copy selected dockerfile from handler_dockerfiles folder (default is enough in most cases) - docker build -t handler . ## Deploying docker image on AWS Fargate +Make sure your AWS credentials are set up correctly (`~/.aws/credentials` exists and has proper values) + Requirements: AWS CLI -Create ECR repository for docker image: -aws ecr create-repository --repository-name handler +Create ECR repository for docker image through aws console or CLI: +`aws ecr create-repository --repository-name handler` + +You can replace `handler` with other name of your choice (here and in subsequent usages) Now you need to push docker image onto ECR repository. Log in to the AWS website and navigate to the Repositories tab under the Elastic Container Service. You should able to see the repository you have just created. Next, click on the repository and click on View Push Commands to get a list of commands that you need to run to be able to push your image to ECR. Follow the steps as they are given. Example steps: -aws ecr get-login --no-include-email --region eu-west-1 +`aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456789.dkr.ecr.us-east-1.amazonaws.com` -sudo docker login -u AWS -p https://123456789.dkr.ecr.eu-west-1.amazonaws.com -sudo docker tag handler:latest 123456789.dkr.ecr.eu-west-1.amazonaws.com/handler:latest +`sudo docker tag handler:latest 123456789.dkr.ecr.us-east-1.amazonaws.com/handler:latest` -sudo docker push 123456789.dkr.ecr.eu-west-1.amazonaws.com/handler:latest +`sudo docker push 123456789.dkr.ecr.us-east-1.amazonaws.com/handler:latest` ## Create Fargate application -First, go to this link https://eu-west-1.console.aws.amazon.com/ecs/home?region=eu-west-1#/getStarted to get started with creating a new Fargate Application. + +Create a Fargate cluster and EFS Volume, then add a new task definition: + Click get started, then select custom container and configure it. Give it some name, image URI can be found in ECR repository, for example: 123456789.dkr.ecr.eu-west-1.amazonaws.com/handler:latest -Click edit on Task definition - set some task definition name, and create proper task execution role which enables using S3. Click save and next. +Click edit on Task definition - set some task definition name, and create proper task execution role which enables using S3 and EFS. -Again next (we don't define load balancer). +Under Storage add Volume of type EFS for one you created, and a mount point under `/mnt/data` -Set cluster name and next and create. - -On the next page, you should be able to see the status of the service you have just created. Wait for the steps to complete and then click on View Service. +You don't need to define anything else for now and can finish the creation. ## Running Hyperflow with AWS Fargate Update your workflow so it uses awsFargateCommand function. -Remember to update config file. +Remember to update config file - tasks_mapping should have a value corresponding to arn of task you just created. + +Afterwards you can run your workflow using `hflow run .` For more details check hyperflow page: https://github.com/hyperflow-wms/hyperflow. + + +## Automated setup + +To create the environment for you, you can run +`cd setup && npm install && node index.js` +which will install the required modules and setup the infrastructure for you. diff --git a/data-provider/Dockerfile b/data-provider/Dockerfile new file mode 100644 index 0000000..8956ae6 --- /dev/null +++ b/data-provider/Dockerfile @@ -0,0 +1,3 @@ +FROM alpine +WORKDIR / +CMD ["sh", "-c", "cp -rf /data/* /mnt/data/ && ls -l /mnt/data/"] \ No newline at end of file diff --git a/handler.js b/handler.js index d9f4178..f41e776 100644 --- a/handler.js +++ b/handler.js @@ -1,212 +1,239 @@ -'use strict'; - +"use strict"; const childProcess = require("child_process"); const fs = require("fs"); const async = require("async"); const aws = require("aws-sdk"); + +aws.config.update({ region: "us-east-1" }); + const s3 = new aws.S3(); function handleRequest(request) { - - const metrics = { - "fargateStart": Date.now(), - "fargateEnd": "", - "downloadStart": "", - "downloadEnd": "", - "executionStart": "", - "executionEnd": "", - "uploadStart": "", - "uploadEnd": "", - }; - - const executable = request.executable; - const args = request.args; - const bucket_name = request.options.bucket; - const prefix = request.options.prefix; - const inputs = request.inputs.map(input => input.name); - const outputs = request.outputs.map(output => output.name); - const files = inputs.slice(); - const logName = request.logName; - files.push(executable); - - console.log("Executable: " + executable); - console.log("Arguments: " + args); - console.log("Inputs: " + inputs); - console.log("Outputs: " + outputs); - console.log("Bucket: " + bucket_name); - console.log("Prefix: " + prefix); - console.log("Stdout: " + request.stdout); - - async.waterfall([ - download, - execute, - upload - ], async function (err) { - if (err) { - console.error("Error: " + err); - process.exit(1) - } else { - console.log("Success"); - metrics.fargateEnd = Date.now(); - const metricsString = "fargate start: " + metrics.fargateStart + " fargate end: " + metrics.fargateEnd + - " download start: " + metrics.downloadStart + " download end: " + metrics.downloadEnd + - " execution start: " + metrics.executionStart + " execution end: " + metrics.executionEnd + - " upload start: " + metrics.uploadStart + " upload end: " + metrics.uploadEnd; - if (logName !== undefined) { - await s3.putObject({ - Bucket: bucket_name, - Key: "logs/" + logName, - ContentType: 'text/plain', - Body: metricsString - }).promise(); + const metrics = { + fargateStart: Date.now(), + fargateEnd: "", + downloadStart: "", + downloadEnd: "", + executionStart: "", + executionEnd: "", + uploadStart: "", + uploadEnd: "", + }; + + const executable = request.executable; + const args = request.args; + const bucket_name = request.options.bucket; + const prefix = request.options.prefix; + const inputs = request.inputs.map((input) => input.name); + const outputs = request.outputs.map((output) => output.name); + const files = inputs.slice(); + const logName = request.logName; + files.push(executable); + + console.log("Executable: " + executable); + console.log("Arguments: " + args); + console.log("Inputs: " + inputs); + console.log("Outputs: " + outputs); + console.log("Bucket: " + bucket_name); + console.log("Prefix: " + prefix); + console.log("Stdout: " + request.stdout); + + async.waterfall([download, execute, upload], async function (err) { + if (err) { + console.error("Error: " + err); + process.exit(1); + } else { + console.log("Success"); + metrics.fargateEnd = Date.now(); + const metricsString = + "fargate start: " + + metrics.fargateStart + + " fargate end: " + + metrics.fargateEnd + + " download start: " + + metrics.downloadStart + + " download end: " + + metrics.downloadEnd + + " execution start: " + + metrics.executionStart + + " execution end: " + + metrics.executionEnd + + " upload start: " + + metrics.uploadStart + + " upload end: " + + metrics.uploadEnd; + console.log(metricsString); + } + }); + // console.log("handleRequest") + + function download(callback) { + // console.log("download start") + metrics.downloadStart = Date.now(); + async.each( + files, + function (file, callback) { + if (file.endsWith(".js") || file.endsWith(".sh")) { + console.log("Downloading " + bucket_name + "/" + prefix + "/" + file); + + const params = { + Bucket: bucket_name, + Key: prefix + "/" + file, + }; + s3.getObject(params, function (err, data) { + if (err) { + console.log("Error downloading file " + JSON.stringify(params)); + process.exit(1); } else { - console.log(metricsString); - } - } - }); - - function download(callback) { - metrics.downloadStart = Date.now(); - async.each(files, function (file, callback) { - - console.log("Downloading " + bucket_name + "/" + prefix + "/" + file); - - const params = { - Bucket: bucket_name, - Key: prefix + "/" + file - }; - s3.getObject(params, function (err, data) { + const path = "/mnt/data/" + file; + fs.writeFile(path, data.Body, function (err) { if (err) { - console.log("Error downloading file " + JSON.stringify(params)); - process.exit(1) - } else { - const path = "/tmp/" + file; - fs.writeFile(path, data.Body, function (err) { - if (err) { - console.log("Unable to save file " + path); - process.exit(1) - } - console.log("Downloaded " + path); - console.log("Downloaded and saved file " + path); - callback(); - }); + console.log("Unable to save file " + path); + process.exit(1); } - }); - }, function (err) { - metrics.downloadEnd = Date.now(); - if (err) { - console.error("Failed to download file:" + err); - process.exit(1) - } else { - console.log("All files have been downloaded successfully"); - callback() + console.log("Downloaded " + path); + console.log("Downloaded and saved file " + path); + callback(); + }); } - }); - } - - function execute(callback) { - metrics.executionStart = Date.now(); - const proc_name = /tmp/ + "/" + executable; - fs.chmodSync(proc_name, "777"); - - let proc; - console.log("Running executable" + proc_name); - - if (proc_name.endsWith(".js")) { - proc = childProcess.fork(proc_name, args, {cwd: "/tmp"}); - } else if (proc_name.endsWith(".jar")) { - let java_args = ['-jar', proc_name]; - const program_args = java_args.concat(args); - proc = childProcess.spawn('java', program_args, {cwd: "/tmp"}); + }); } else { - proc = childProcess.spawn(proc_name, args, {cwd: "/tmp"}); - - proc.stdout.on("data", function (exedata) { - console.log("Stdout: " + executable + exedata); - }); - - proc.stderr.on("data", function (exedata) { - console.log("Stderr: " + executable + exedata); - }); + // console.log("local file " + file) + if (callback) { + callback(); + } } - - if (request.stdout) { - let stdoutStream = fs.createWriteStream("/tmp" + "/" + request.stdout, {flags: 'w'}); - proc.stdout.pipe(stdoutStream); + }, + function (err) { + metrics.downloadEnd = Date.now(); + if (err) { + console.error("Failed to download file:" + err); + process.exit(1); + } else { + console.log("All files have been downloaded successfully"); + callback(); } - - proc.on("error", function (code) { - console.error("Error!!" + executable + JSON.stringify(code)); - }); - proc.on("exit", function () { - console.log("My exe exit " + executable); - }); - - proc.on("close", function () { - console.log("My exe close " + executable); - metrics.executionEnd = Date.now(); - callback() - }); + } + ); + } + + function execute(callback) { + metrics.executionStart = Date.now(); + let proc_name = executable; + if (executable.endsWith(".js") || executable.endsWith(".sh")) { + // console.log("remote executable " + executable) + fs.chmodSync(proc_name, "777"); } - function upload(callback) { - metrics.uploadStart = Date.now(); - async.each(outputs, function (file, callback) { + let proc; + console.log("Running executable" + proc_name); + + if (proc_name.endsWith(".js")) { + proc = childProcess.fork(proc_name, args, { cwd: "/mnt/data/" }); + } else if (proc_name.endsWith(".jar")) { + let java_args = ["-jar", proc_name]; + const program_args = java_args.concat(args); + proc = childProcess.spawn("java", program_args, { cwd: "/mnt/data/" }); + } else { + proc = childProcess.exec(proc_name + " " + args.join(" "), { + cwd: "/mnt/data/", + }); + + proc.stdout.on("data", function (exedata) { + console.log("Stdout: " + executable + exedata); + }); + + proc.stderr.on("data", function (exedata) { + console.log("Stderr: " + executable + exedata); + }); + } - console.log("Uploading " + bucket_name + "/" + prefix + "/" + file); - const path = "/tmp/" + file; + if (request.stdout) { + let stdoutStream = fs.createWriteStream("/mnt/data/" + request.stdout, { + flags: "w", + }); + proc.stdout.pipe(stdoutStream); + } - fs.readFile(path, function (err, data) { - if (err) { - console.log("Error reading file " + path); - process.exit(1) - } + proc.on("error", function (code) { + console.error("Error!!" + executable + JSON.stringify(code)); + }); + proc.on("exit", function () { + console.log("My exe exit " + executable); + }); - const params = { - Bucket: bucket_name, - Key: prefix + "/" + file, - Body: data - }; - - s3.putObject(params, function (err) { - if (err) { - console.log("Error uploading file " + file); - process.exit(1) - } - console.log("Uploaded file " + file); - callback(); - }); - }); - - }, function (err) { - metrics.uploadEnd = Date.now(); - if (err) { - console.log("Error uploading file " + err); - process.exit(1) - } else { - console.log("All files have been uploaded successfully"); - callback() - } - }); - } + proc.on("close", function () { + console.log("My exe close " + executable); + metrics.executionEnd = Date.now(); + callback(); + }); + } + + function upload(callback) { + // console.log("upload start") + // console.log("outputs: " + outputs) + console.log("data: ", fs.readdirSync("/mnt/data")); + // console.log("tmp: ",fs.readdirSync("/")) + + metrics.uploadStart = Date.now(); + async.each( + outputs, + function (file, callback) { + // console.log("Uploading " + bucket_name + "/" + prefix + "/" + file); + // // console.log("Uploading " + bucket_name + "/" + prefix + "/" + file); + // const oldpath = file; + // const newpath = "/mnt/data/" + file; + // fs.copyFile(oldpath,newpath, (err)=> console.log(err)) + // callback() + // fs.readFile(path, function (err, data) { + // if (err) { + // console.log("Error reading file " + path); + // process.exit(1) + // } + // const params = { + // Bucket: bucket_name, + // Key: prefix + "/" + file, + // Body: data + // }; + // s3.putObject(params, function (err) { + // if (err) { + // console.log("Error uploading file " + file); + // process.exit(1) + // } + // console.log("Uploaded file " + file); + // callback(); + // }); + // }); + }, + function (err) { + metrics.uploadEnd = Date.now(); + if (err) { + console.log("Error uploading file " + err); + process.exit(1); + } else { + console.log("All files have been uploaded successfully"); + callback(); + } + } + ); + } } let arg = process.argv[2]; if (!arg) { - console.log("Received empty request, exiting..."); - process.exit(1); + console.log("Received empty request, exiting..."); + process.exit(1); } if (arg.startsWith("S3")) { - const params = JSON.parse(arg.split("=")[1]); - console.log("Getting executable config from S3: " + JSON.stringify(params)); - s3.getObject(params, function (err, data) { - if (err) - return err; - arg = data.Body.toString(); - handleRequest(JSON.parse(arg)); - }); -} else { + const params = JSON.parse(arg.split("=")[1]); + console.log("Getting executable config from S3: " + JSON.stringify(params)); + s3.getObject(params, function (err, data) { + if (err) return err; + arg = data.Body.toString(); handleRequest(JSON.parse(arg)); -} \ No newline at end of file + }); +} else { + handleRequest(JSON.parse(arg)); +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..d3bd840 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,880 @@ +{ + "name": "aws-fargate-executor", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "aws-fargate-executor", + "version": "1.0.0", + "dependencies": { + "@hyperflow/job-executor": "^1.3.4", + "async": "^2.6.2", + "aws-sdk": "^2.429.0" + } + }, + "node_modules/@hyperflow/job-executor": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@hyperflow/job-executor/-/job-executor-1.3.4.tgz", + "integrity": "sha512-opvV5M39ayr5k96zfRokBq39AayKXnuwa1h6HV/ffmvVbRIbjfbzl5RHNGbGYDL8YSKK0lg08nrINdhVpb0pVw==", + "dependencies": { + "@stroncium/procfs": "^1.0.0", + "amqp": "latest", + "amqplib": "^0.8.0", + "docopt": "^0.6.2", + "log4js": "^6.1.0", + "pidtree": "^0.3.0", + "pidusage": "^2.0.18", + "read-env": "^2.0.0", + "redis": "^3.1.1", + "shortid": "^2.2.15", + "systeminformation": "^5.6.4", + "uuid": "^8.3.2" + }, + "bin": { + "hflow-job-execute": "jobexec.js", + "hflow-job-listener.js": "hflow-job-listener.js" + } + }, + "node_modules/@hyperflow/job-executor/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/@stroncium/procfs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@stroncium/procfs/-/procfs-1.2.1.tgz", + "integrity": "sha512-X1Iui3FUNZP18EUvysTHxt+Avu2nlVzyf90YM8OYgP6SGzTzzX/0JgObfO1AQQDzuZtNNz29bVh8h5R97JrjxA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@types/camelcase": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@types/camelcase/-/camelcase-5.2.0.tgz", + "integrity": "sha512-zhHaryYYUUsJ1h6Rq4hisPkljY7c2bkC5PFYQbom5fyKloGJEDK+wdsw2L4hnBwXr4plGjW6D/UVJBbNbOzVpQ==", + "deprecated": "This is a stub types definition. camelcase provides its own type definitions, so you do not need this installed.", + "dependencies": { + "camelcase": "*" + } + }, + "node_modules/amqp": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/amqp/-/amqp-0.2.7.tgz", + "integrity": "sha512-AtXW9QEhSf2diJHn4Fmeo9Zdb1LMyEer6dUCOxzjEb7Fxh3CBgad3nmB8LTXDYsDRbdRfHruGCFYG7T+4qilww==", + "dependencies": { + "lodash": "^4.0.0" + } + }, + "node_modules/amqplib": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.8.0.tgz", + "integrity": "sha512-icU+a4kkq4Y1PS4NNi+YPDMwdlbFcZ1EZTQT2nigW3fvOb6AOgUQ9+Mk4ue0Zu5cBg/XpDzB40oH10ysrk2dmA==", + "dependencies": { + "bitsyntax": "~0.1.0", + "bluebird": "^3.7.2", + "buffer-more-ints": "~1.0.0", + "readable-stream": "1.x >=1.1.9", + "safe-buffer": "~5.2.1", + "url-parse": "~1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-sdk": { + "version": "2.1584.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1584.0.tgz", + "integrity": "sha512-57Qizb+bLOhrBLWQSWw6WXTtbO/lFKzLouHxTfm/QeXm38gs0Q0knFxhdH+sWc/DPPJYSRGy7MNiuQcmsq5zxA==", + "hasInstallScript": true, + "dependencies": { + "buffer": "4.9.2", + "events": "1.1.1", + "ieee754": "1.1.13", + "jmespath": "0.16.0", + "querystring": "0.2.0", + "sax": "1.2.1", + "url": "0.10.3", + "util": "^0.12.4", + "uuid": "8.0.0", + "xml2js": "0.6.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "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/bitsyntax": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.1.0.tgz", + "integrity": "sha512-ikAdCnrloKmFOugAfxWws89/fPc+nw0OOG1IzIE72uSOg/A3cYptKCjSUhDTuj7fhsJtzkzlv7l3b8PzRHLN0Q==", + "dependencies": { + "buffer-more-ints": "~1.0.0", + "debug": "~2.6.9", + "safe-buffer": "~5.1.2" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/bitsyntax/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, + "node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/buffer-more-ints": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz", + "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==" + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/date-format": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", + "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/denque": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/docopt": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/docopt/-/docopt-0.6.2.tgz", + "integrity": "sha512-NqTbaYeE4gA/wU1hdKFdU+AFahpDOpgGLzHP42k6H6DKExJd0A55KEVWYhL9FEmHmgeLvEU2vuKXDuU+4yToOw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" + }, + "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==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==" + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "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==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "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==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/jmespath": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", + "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/log4js": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", + "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "flatted": "^3.2.7", + "rfdc": "^1.3.0", + "streamroller": "^3.1.5" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/log4js/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/log4js/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==" + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/nanoid": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", + "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==" + }, + "node_modules/pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pidusage": { + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-2.0.21.tgz", + "integrity": "sha512-cv3xAQos+pugVX+BfXpHsbyz/dLzX+lr44zNMsYiGxUw+kV5sgQCIcLd1z+0vq+KyC7dJ+/ts2PsfgWfSC3WXA==", + "dependencies": { + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==" + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, + "node_modules/read-env": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-env/-/read-env-2.0.0.tgz", + "integrity": "sha512-gCuo85JH2aWt23HVeFzUUhpLzCRtc9O0jjvpMDG/3vue2aOp7/XllAQjSyL8xGqBifGNYbnWLE0PAqi4AWMBlA==", + "dependencies": { + "@types/camelcase": "5.2.0", + "camelcase": "5.3.1" + } + }, + "node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/readable-stream/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, + "node_modules/redis": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz", + "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", + "dependencies": { + "denque": "^1.5.0", + "redis-commands": "^1.7.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-redis" + } + }, + "node_modules/redis-commands": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", + "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==" + }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, + "node_modules/rfdc": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==" + }, + "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==", + "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/sax": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", + "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shortid": { + "version": "2.2.16", + "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.16.tgz", + "integrity": "sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dependencies": { + "nanoid": "^2.1.0" + } + }, + "node_modules/streamroller": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", + "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/streamroller/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/streamroller/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==" + }, + "node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" + }, + "node_modules/systeminformation": { + "version": "5.22.7", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.22.7.tgz", + "integrity": "sha512-AWxlP05KeHbpGdgvZkcudJpsmChc2Y5Eo/GvxG/iUA/Aws5LZKHAMSeAo+V+nD+nxWZaxrwpWcnx4SH3oxNL3A==", + "os": [ + "darwin", + "linux", + "win32", + "freebsd", + "openbsd", + "netbsd", + "sunos", + "android" + ], + "bin": { + "systeminformation": "lib/cli.js" + }, + "engines": { + "node": ">=8.0.0" + }, + "funding": { + "type": "Buy me a coffee", + "url": "https://www.buymeacoffee.com/systeminfo" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/url": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", + "integrity": "sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ==", + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/uuid": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz", + "integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + } + } +} diff --git a/package.json b/package.json index b11ebd2..b71b705 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "start": "node handler.js" }, "dependencies": { + "@hyperflow/job-executor": "^1.3.4", "async": "^2.6.2", "aws-sdk": "^2.429.0" } diff --git a/setup/dataUtils.js b/setup/dataUtils.js new file mode 100644 index 0000000..0ac19fd --- /dev/null +++ b/setup/dataUtils.js @@ -0,0 +1,128 @@ +import { CreateBucketCommand } from "@aws-sdk/client-s3"; +import { + CreateFunctionCommand, + InvokeCommand, + GetFunctionCommand, +} from "@aws-sdk/client-lambda"; +import { RunTaskCommand, DescribeTasksCommand } from "@aws-sdk/client-ecs"; +import fs from "fs"; + +const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + +const ROLE_ARN_DEFAULT = "arn:aws:iam::471112732460:role/LabRole"; + +export async function createS3Bucket(s3Client) { + try { + const bucketParams = { + Bucket: `hyperflow-fargate-${Date.now()}`, + }; + + // Create the S3 bucket + const data = await s3Client.send(new CreateBucketCommand(bucketParams)); + + console.log("S3 bucket created successfully:", data); + return data; + } catch (err) { + console.error("Error creating S3 bucket:", err); + } +} + +export async function runDataSyncTask( + ecsClient, + clusterArn, + subnetId, + taskDefinitionArn, +) { + try { + const params = { + cluster: clusterArn, + launchType: "FARGATE", + taskDefinition: taskDefinitionArn, + count: 1, + networkConfiguration: { + awsvpcConfiguration: { + subnets: [subnetId], + securityGroups: [], + assignPublicIp: "ENABLED", + }, + }, + }; + + const command = new RunTaskCommand(params); + const response = await ecsClient.send(command); + + let syncFinished = false; + while (!syncFinished) { + const taskArn = response.tasks[0].taskArn; + const probeCommand = new DescribeTasksCommand({ + cluster: clusterArn, + tasks: [taskArn], + }); + const probeResponse = await ecsClient.send(probeCommand); + const task = probeResponse.tasks[0]; + if (task.lastStatus === "STOPPED") { + syncFinished = true; + return; + } else { + console.log("Data sync task still running..."); + await sleep(5000); // Wait for 5 seconds before the next check + } + } + } catch (err) { + console.error("Error executing ECS Fargate task:", err); + } +} + +export async function syncImageData(dataImage, lambdaClient) { + try { + const params = { + FunctionName: "HyperflowDataImageUpdater", + InvocationType: "RequestResponse", + Payload: JSON.stringify({ + taskDefinition: "hyperflow-data-provider", + containerName: "data", + dataImage, + }), + }; + const data = await lambdaClient.send(new InvokeCommand(params)); + console.log("Lambda function invoked successfully:", data); + } catch (err) { + console.error("Error invoking Lambda function:", err); + } +} + +export async function createLambdaFunction(lambdaClient) { + try { + const zipFile = fs.readFileSync("lambda.zip"); + const functionParams = { + Code: { + ZipFile: zipFile, + }, + FunctionName: "HyperflowDataImageUpdater", + Handler: "lambda_function.lambda_handler", + Role: ROLE_ARN_DEFAULT, + Runtime: "python3.10", + Timeout: 30, + }; + + const data = await lambdaClient.send( + new CreateFunctionCommand(functionParams), + ); + + let isReady = data.State === "Active"; + while (!isReady) { + const probeCommand = new GetFunctionCommand({ + FunctionName: "HyperflowDataImageUpdater", + }); + const response = await lambdaClient.send(probeCommand); + isReady = response.Configuration.State === "Active"; + await sleep(5000); // Wait for 5 seconds before the next check + } + + console.log("Lambda function created successfully:", data); + return data; + } catch (err) { + console.error("Error creating Lambda function:", err); + return { FunctionName: "HyperflowDataImageUpdater" }; + } +} diff --git a/setup/ecsUtils.js b/setup/ecsUtils.js new file mode 100644 index 0000000..4456daa --- /dev/null +++ b/setup/ecsUtils.js @@ -0,0 +1,204 @@ +import { CreateClusterCommand } from "@aws-sdk/client-ecs"; + +import { RegisterTaskDefinitionCommand } from "@aws-sdk/client-ecs"; +const CPU_DEFAULT = "512"; +const MEMORY_DEFAULT = "1024"; + +const ROLE_ARN_DEFAULT = "arn:aws:iam::471112732460:role/LabRole"; + +const MONTAGE_WORKER_IMAGE = + "471112732460.dkr.ecr.us-east-1.amazonaws.com/handler-montage:latest"; + +const TASK_DEFINITION_BASE = { + taskRoleArn: ROLE_ARN_DEFAULT, + executionRoleArn: ROLE_ARN_DEFAULT, + networkMode: "awsvpc", + requiresCompatibilities: ["FARGATE"], + cpu: CPU_DEFAULT, + memory: MEMORY_DEFAULT, + runtimePlatform: { + cpuArchitecture: "X86_64", + operatingSystemFamily: "LINUX", + }, +}; + +function getLogConfiguration(name) { + return { + logDriver: "awslogs", + options: { + "awslogs-group": `/ecs/${name}`, + "awslogs-create-group": "true", + "awslogs-region": "us-east-1", + "awslogs-stream-prefix": "ecs", + }, + secretOptions: [], + }; +} + +async function createDataProviderTaskDefinition(ecsClient, efsData) { + const taskDefinition = { + ...TASK_DEFINITION_BASE, + family: "hyperflow-data-provider", + + containerDefinitions: [ + { + name: "data", + image: "471112732460.dkr.ecr.us-east-1.amazonaws.com/data-provider-container:latest", + cpu: 0, + portMappings: [ + { + name: "data-80-tcp", + containerPort: 80, + hostPort: 80, + protocol: "tcp", + appProtocol: "http", + }, + ], + essential: false, + environment: [], + environmentFiles: [], + mountPoints: [], + volumesFrom: [], + ulimits: [], + logConfiguration: getLogConfiguration("data"), + systemControls: [], + }, + { + name: "script", + image: "471112732460.dkr.ecr.us-east-1.amazonaws.com/data-provider-script:latest", + cpu: 0, + portMappings: [], + essential: true, + environment: [], + environmentFiles: [], + mountPoints: [ + { + sourceVolume: "efsdata", + containerPath: "/mnt/data", + readOnly: false, + }, + ], + volumesFrom: [ + { + sourceContainer: "data", + readOnly: true, + }, + ], + systemControls: [], + logConfiguration: getLogConfiguration("data-provider-script"), + }, + ], + volumes: [ + { + name: "efsdata", + efsVolumeConfiguration: { + fileSystemId: efsData.FileSystemId, + rootDirectory: "/", + }, + }, + ], + }; + try { + const data = await ecsClient.send( + new RegisterTaskDefinitionCommand(taskDefinition), + ); + + console.log( + "Data provider worker task definition registered successfully:", + data.taskDefinition, + ); + return data.taskDefinition; + } catch (err) { + console.error("Error registering data provider task definition:", err); + } +} + +async function createMontageWorkerTaskDefinition(ecsClient, efsData) { + const taskDefinition = { + ...TASK_DEFINITION_BASE, + family: "hyperflow-montage-worker", + containerDefinitions: [ + { + name: "montage-worker", + image: MONTAGE_WORKER_IMAGE, + cpu: 0, + portMappings: [ + { + name: "hyperflow-montage-worker-80-tcp", + containerPort: 80, + hostPort: 80, + protocol: "tcp", + appProtocol: "http", + }, + ], + essential: true, + environment: [], + environmentFiles: [], + mountPoints: [ + { + sourceVolume: "efs-volume", + containerPath: "/mnt/data", + readOnly: false, + }, + ], + volumesFrom: [], + ulimits: [], + logConfiguration: getLogConfiguration( + "hyperflow-montage-worker", + ), + systemControls: [], + }, + ], + volumes: [ + { + name: "efs-volume", + efsVolumeConfiguration: { + fileSystemId: efsData.FileSystemId, + rootDirectory: "/", + }, + }, + ], + }; + + try { + const data = await ecsClient.send( + new RegisterTaskDefinitionCommand(taskDefinition), + ); + + console.log( + "Montage worker task definition registered successfully:", + data.taskDefinition, + ); + return data.taskDefinition; + } catch (err) { + console.error("Error registering montage worker task definition:", err); + } +} + +export async function createTaskDefinitions(ecsClient, efsData) { + const [montageWorkerTaskDefinition, dataProviderTaskDefinition] = + await Promise.all([ + createMontageWorkerTaskDefinition(ecsClient, efsData), + createDataProviderTaskDefinition(ecsClient, efsData), + ]); + return { + worker: montageWorkerTaskDefinition, + dataProvider: dataProviderTaskDefinition, + }; +} + +export async function setupCluster(ecsClient) { + // Define cluster parameters + const params = { + clusterName: "hyperflow-cluster", + }; + + try { + // Create the cluster + const data = await ecsClient.send(new CreateClusterCommand(params)); + console.log("Cluster created successfully:", data.cluster); + return data.cluster; + } catch (err) { + console.error("Error creating cluster:", err); + } +} diff --git a/setup/efsUtils.js b/setup/efsUtils.js new file mode 100644 index 0000000..5ecf999 --- /dev/null +++ b/setup/efsUtils.js @@ -0,0 +1,79 @@ +import { + CreateFileSystemCommand, + CreateMountTargetCommand, + DescribeFileSystemsCommand, + DescribeMountTargetsCommand, +} from "@aws-sdk/client-efs"; + +export const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + +export async function createEFSFileSystem(efsClient, vpcData) { + try { + const fileSystemParams = { + CreationToken: `hyperflow-efs-volume-${Date.now()}`, + PerformanceMode: "generalPurpose", + Encrypted: false, + }; + + const fileSystemData = await efsClient.send( + new CreateFileSystemCommand(fileSystemParams), + ); + await waitForFileSystemAvailable( + efsClient, + fileSystemData.FileSystemId, + ); + console.log("EFS file system created successfully:", fileSystemData); + + for (let i = 0; i < vpcData.subnets.length; i++) { + const subnet = vpcData.subnets[i]; + const mountTargetParams = { + FileSystemId: fileSystemData.FileSystemId, + SubnetId: subnet.SubnetId, + SecurityGroups: [vpcData.securityGroup.GroupId], + }; + const mountTargetData = await efsClient.send( + new CreateMountTargetCommand(mountTargetParams), + ); + } + const probeParams = { + FileSystemId: fileSystemData.FileSystemId, + }; + let ready = false; + while (!ready) { + const data = await efsClient.send( + new DescribeMountTargetsCommand(probeParams), + ); + if (data.MountTargets[0].LifeCycleState === "available") { + ready = true; + } + await sleep(5000); + } + console.log("Mount targets created successfully"); + + return fileSystemData; + } catch (err) { + console.error("Error creating EFS file system or mount target:", err); + } +} + +async function waitForFileSystemAvailable(efsClient, fileSystemId) { + let isAvailable = false; + + while (!isAvailable) { + const describeParams = { + FileSystemId: fileSystemId, + }; + + const data = await efsClient.send( + new DescribeFileSystemsCommand(describeParams), + ); + const fs = data.FileSystems[0]; + if (fs.LifeCycleState === "available") { + isAvailable = true; + return; + } else { + console.log("Waiting for file system to become available..."); + await sleep(5000); // Wait for 5 seconds before the next check + } + } +} diff --git a/setup/index.js b/setup/index.js new file mode 100644 index 0000000..f5b3d62 --- /dev/null +++ b/setup/index.js @@ -0,0 +1,89 @@ +import { ECSClient } from "@aws-sdk/client-ecs"; +import { EFSClient } from "@aws-sdk/client-efs"; +import { EC2Client } from "@aws-sdk/client-ec2"; +import { LambdaClient } from "@aws-sdk/client-lambda"; +import { S3Client } from "@aws-sdk/client-s3"; +import { hideBin } from "yargs/helpers"; +import yargs from "yargs"; + +import { createVPCAndSubnets } from "./vpcUtils.js"; +import { createEFSFileSystem, sleep } from "./efsUtils.js"; +import { createTaskDefinitions, setupCluster } from "./ecsUtils.js"; +import { + createS3Bucket, + runDataSyncTask, + syncImageData, + createLambdaFunction, +} from "./dataUtils.js"; + +const REGION = "us-east-1"; + +async function main(args) { + const ecsClient = new ECSClient({ region: REGION }); + const ec2Client = new EC2Client({ region: REGION }); + const efsClient = new EFSClient({ region: REGION }); + const s3Client = new S3Client({ region: REGION }); + const lambdaClient = new LambdaClient({ region: REGION }); + + const vpcData = await createVPCAndSubnets(ec2Client); + if (vpcData.length === 0) { + console.error("Error creating VPC and subnets"); + return; + } + const securityGroupId = vpcData.securityGroup.GroupId; + const clusterData = await setupCluster(ecsClient); + const efsData = await createEFSFileSystem( + efsClient, + vpcData, + securityGroupId + ); + const taskDefinitions = await createTaskDefinitions(ecsClient, efsData); + console.log("Task definitions created successfully:", taskDefinitions); + const s3BucketData = await createS3Bucket(s3Client); + console.log("S3 bucket name:", s3BucketData.Location); + await createLambdaFunction(lambdaClient); + + if (args.dataImage) { + console.log("Running data sync, can take up to a few minutes..."); + await syncImageData(args.dataImage, lambdaClient); + await sleep(60000); + await runDataSyncTask( + ecsClient, + clusterData.clusterArn, + vpcData.subnets[0].SubnetId, + taskDefinitions.dataProvider.taskDefinitionArn + ); + console.log("Data sync complete"); + } + + console.log( + "AWSFargateCommandConfig: \n", + ` + exports.cluster_arn = ${clusterData.clusterArn}; + exports.subnet_1 = ${vpcData.subnets[0].SubnetId}; + exports.metrics = true; + + exports.options = { + "bucket": ${s3BucketData.Location}, + "prefix": "hyperflow", + }; + + exports.tasks_mapping = { + "default": "${taskDefinitions.worker.taskDefinitionArn}", + "dataProvider": "${taskDefinitions.dataProvider.taskDefinitionArn}", + }; + ` + ); +} + +const argv = yargs(hideBin(process.argv)) + .option("dataImage", { + alias: "d", + description: "Image containing data for workflow", + type: "string", + demandOption: false, + }) + .help() + .alias("help", "h").argv; + +main(argv); diff --git a/setup/lambda.zip b/setup/lambda.zip new file mode 100644 index 0000000..82efb50 Binary files /dev/null and b/setup/lambda.zip differ diff --git a/setup/package-lock.json b/setup/package-lock.json new file mode 100644 index 0000000..11d7aad --- /dev/null +++ b/setup/package-lock.json @@ -0,0 +1,1933 @@ +{ + "name": "fargate-setup", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fargate-setup", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@aws-sdk/client-ec2": "^3.592.0", + "@aws-sdk/client-ecs": "^3.592.0", + "@aws-sdk/client-efs": "^3.592.0", + "@aws-sdk/client-lambda": "^3.592.0", + "@aws-sdk/client-s3": "^3.592.0", + "prettier": "^3.3.1", + "yargs": "^17.7.2" + } + }, + "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/crc32c": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-3.0.0.tgz", + "integrity": "sha512-ENNPPManmnVJ4BTXlOjAgD7URidbAznURqD0KvfREyc4o20DPYdEldU1f5cQ7Jbj0CJJSPaMIk/9ZshdB3210w==", + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/crc32c/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/sha1-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-3.0.0.tgz", + "integrity": "sha512-NJth5c997GLHs6nOYTzFKTbYdMNA6/1XlKVgnZoaZcQ7z7UJlOgj2JdbHE8tiYLS3fzXNCguct77SPGat2raSw==", + "dependencies": { + "@aws-crypto/ie11-detection": "^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/sha1-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-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-ec2": { + "version": "3.592.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-ec2/-/client-ec2-3.592.0.tgz", + "integrity": "sha512-LTt+CUwKknyeLbUdUO+kOzC4WoKahJyQovtf+93liurPqKFtyijQk6ZNryFJv6+h/toW4lFnWq0H306OeY77Wg==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sso-oidc": "3.592.0", + "@aws-sdk/client-sts": "3.592.0", + "@aws-sdk/core": "3.592.0", + "@aws-sdk/credential-provider-node": "3.592.0", + "@aws-sdk/middleware-host-header": "3.577.0", + "@aws-sdk/middleware-logger": "3.577.0", + "@aws-sdk/middleware-recursion-detection": "3.577.0", + "@aws-sdk/middleware-sdk-ec2": "3.587.0", + "@aws-sdk/middleware-user-agent": "3.587.0", + "@aws-sdk/region-config-resolver": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-endpoints": "3.587.0", + "@aws-sdk/util-user-agent-browser": "3.577.0", + "@aws-sdk/util-user-agent-node": "3.587.0", + "@smithy/config-resolver": "^3.0.1", + "@smithy/core": "^2.2.0", + "@smithy/fetch-http-handler": "^3.0.1", + "@smithy/hash-node": "^3.0.0", + "@smithy/invalid-dependency": "^3.0.0", + "@smithy/middleware-content-length": "^3.0.0", + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/middleware-retry": "^3.0.3", + "@smithy/middleware-serde": "^3.0.0", + "@smithy/middleware-stack": "^3.0.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/node-http-handler": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/url-parser": "^3.0.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.3", + "@smithy/util-defaults-mode-node": "^3.0.3", + "@smithy/util-endpoints": "^2.0.1", + "@smithy/util-middleware": "^3.0.0", + "@smithy/util-retry": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "@smithy/util-waiter": "^3.0.0", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-ecs": { + "version": "3.592.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-ecs/-/client-ecs-3.592.0.tgz", + "integrity": "sha512-UH4gKCRcacmWkzcqadfmQGIHok/grw3a+AipUeM2P3XA6JYVExyryxbxQ+BrqMmZtvrEX5/KF9NSBKrikHnOEg==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sso-oidc": "3.592.0", + "@aws-sdk/client-sts": "3.592.0", + "@aws-sdk/core": "3.592.0", + "@aws-sdk/credential-provider-node": "3.592.0", + "@aws-sdk/middleware-host-header": "3.577.0", + "@aws-sdk/middleware-logger": "3.577.0", + "@aws-sdk/middleware-recursion-detection": "3.577.0", + "@aws-sdk/middleware-user-agent": "3.587.0", + "@aws-sdk/region-config-resolver": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-endpoints": "3.587.0", + "@aws-sdk/util-user-agent-browser": "3.577.0", + "@aws-sdk/util-user-agent-node": "3.587.0", + "@smithy/config-resolver": "^3.0.1", + "@smithy/core": "^2.2.0", + "@smithy/fetch-http-handler": "^3.0.1", + "@smithy/hash-node": "^3.0.0", + "@smithy/invalid-dependency": "^3.0.0", + "@smithy/middleware-content-length": "^3.0.0", + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/middleware-retry": "^3.0.3", + "@smithy/middleware-serde": "^3.0.0", + "@smithy/middleware-stack": "^3.0.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/node-http-handler": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/url-parser": "^3.0.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.3", + "@smithy/util-defaults-mode-node": "^3.0.3", + "@smithy/util-endpoints": "^2.0.1", + "@smithy/util-middleware": "^3.0.0", + "@smithy/util-retry": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "@smithy/util-waiter": "^3.0.0", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-efs": { + "version": "3.592.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-efs/-/client-efs-3.592.0.tgz", + "integrity": "sha512-SYWkyhLL9Fk6qxYD34qDNgSG/DBhnTps8yqjGE0Gse2IfqiWGYOoUjLFWK16D6ifLH7hfZrsE0MWIHQ6bIiPBQ==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sso-oidc": "3.592.0", + "@aws-sdk/client-sts": "3.592.0", + "@aws-sdk/core": "3.592.0", + "@aws-sdk/credential-provider-node": "3.592.0", + "@aws-sdk/middleware-host-header": "3.577.0", + "@aws-sdk/middleware-logger": "3.577.0", + "@aws-sdk/middleware-recursion-detection": "3.577.0", + "@aws-sdk/middleware-user-agent": "3.587.0", + "@aws-sdk/region-config-resolver": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-endpoints": "3.587.0", + "@aws-sdk/util-user-agent-browser": "3.577.0", + "@aws-sdk/util-user-agent-node": "3.587.0", + "@smithy/config-resolver": "^3.0.1", + "@smithy/core": "^2.2.0", + "@smithy/fetch-http-handler": "^3.0.1", + "@smithy/hash-node": "^3.0.0", + "@smithy/invalid-dependency": "^3.0.0", + "@smithy/middleware-content-length": "^3.0.0", + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/middleware-retry": "^3.0.3", + "@smithy/middleware-serde": "^3.0.0", + "@smithy/middleware-stack": "^3.0.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/node-http-handler": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/url-parser": "^3.0.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.3", + "@smithy/util-defaults-mode-node": "^3.0.3", + "@smithy/util-endpoints": "^2.0.1", + "@smithy/util-middleware": "^3.0.0", + "@smithy/util-retry": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-lambda": { + "version": "3.592.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.592.0.tgz", + "integrity": "sha512-uCtyrccg+qZ/KbZtY9OHb8dXG59yYDvoQULiQaj+73XkI/P4Z69prflg87cA5UpXoSeoAinCahwyJM5+G/EXYw==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sso-oidc": "3.592.0", + "@aws-sdk/client-sts": "3.592.0", + "@aws-sdk/core": "3.592.0", + "@aws-sdk/credential-provider-node": "3.592.0", + "@aws-sdk/middleware-host-header": "3.577.0", + "@aws-sdk/middleware-logger": "3.577.0", + "@aws-sdk/middleware-recursion-detection": "3.577.0", + "@aws-sdk/middleware-user-agent": "3.587.0", + "@aws-sdk/region-config-resolver": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-endpoints": "3.587.0", + "@aws-sdk/util-user-agent-browser": "3.577.0", + "@aws-sdk/util-user-agent-node": "3.587.0", + "@smithy/config-resolver": "^3.0.1", + "@smithy/core": "^2.2.0", + "@smithy/eventstream-serde-browser": "^3.0.0", + "@smithy/eventstream-serde-config-resolver": "^3.0.0", + "@smithy/eventstream-serde-node": "^3.0.0", + "@smithy/fetch-http-handler": "^3.0.1", + "@smithy/hash-node": "^3.0.0", + "@smithy/invalid-dependency": "^3.0.0", + "@smithy/middleware-content-length": "^3.0.0", + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/middleware-retry": "^3.0.3", + "@smithy/middleware-serde": "^3.0.0", + "@smithy/middleware-stack": "^3.0.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/node-http-handler": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/url-parser": "^3.0.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.3", + "@smithy/util-defaults-mode-node": "^3.0.3", + "@smithy/util-endpoints": "^2.0.1", + "@smithy/util-middleware": "^3.0.0", + "@smithy/util-retry": "^3.0.0", + "@smithy/util-stream": "^3.0.1", + "@smithy/util-utf8": "^3.0.0", + "@smithy/util-waiter": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-s3": { + "version": "3.592.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.592.0.tgz", + "integrity": "sha512-abn1XYk9HW2nXIvyD6ldwrNcF5/7a2p06OSWEr7zVTo954kArg8N0yTsy83ezznEHZfaZpdZn/DLDl2GxrE1Xw==", + "dependencies": { + "@aws-crypto/sha1-browser": "3.0.0", + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sso-oidc": "3.592.0", + "@aws-sdk/client-sts": "3.592.0", + "@aws-sdk/core": "3.592.0", + "@aws-sdk/credential-provider-node": "3.592.0", + "@aws-sdk/middleware-bucket-endpoint": "3.587.0", + "@aws-sdk/middleware-expect-continue": "3.577.0", + "@aws-sdk/middleware-flexible-checksums": "3.587.0", + "@aws-sdk/middleware-host-header": "3.577.0", + "@aws-sdk/middleware-location-constraint": "3.577.0", + "@aws-sdk/middleware-logger": "3.577.0", + "@aws-sdk/middleware-recursion-detection": "3.577.0", + "@aws-sdk/middleware-sdk-s3": "3.587.0", + "@aws-sdk/middleware-signing": "3.587.0", + "@aws-sdk/middleware-ssec": "3.577.0", + "@aws-sdk/middleware-user-agent": "3.587.0", + "@aws-sdk/region-config-resolver": "3.587.0", + "@aws-sdk/signature-v4-multi-region": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-endpoints": "3.587.0", + "@aws-sdk/util-user-agent-browser": "3.577.0", + "@aws-sdk/util-user-agent-node": "3.587.0", + "@aws-sdk/xml-builder": "3.575.0", + "@smithy/config-resolver": "^3.0.1", + "@smithy/core": "^2.2.0", + "@smithy/eventstream-serde-browser": "^3.0.0", + "@smithy/eventstream-serde-config-resolver": "^3.0.0", + "@smithy/eventstream-serde-node": "^3.0.0", + "@smithy/fetch-http-handler": "^3.0.1", + "@smithy/hash-blob-browser": "^3.0.0", + "@smithy/hash-node": "^3.0.0", + "@smithy/hash-stream-node": "^3.0.0", + "@smithy/invalid-dependency": "^3.0.0", + "@smithy/md5-js": "^3.0.0", + "@smithy/middleware-content-length": "^3.0.0", + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/middleware-retry": "^3.0.3", + "@smithy/middleware-serde": "^3.0.0", + "@smithy/middleware-stack": "^3.0.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/node-http-handler": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/url-parser": "^3.0.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.3", + "@smithy/util-defaults-mode-node": "^3.0.3", + "@smithy/util-endpoints": "^2.0.1", + "@smithy/util-retry": "^3.0.0", + "@smithy/util-stream": "^3.0.1", + "@smithy/util-utf8": "^3.0.0", + "@smithy/util-waiter": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-sso": { + "version": "3.592.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.592.0.tgz", + "integrity": "sha512-w+SuW47jQqvOC7fonyjFjsOh3yjqJ+VpWdVrmrl0E/KryBE7ho/Wn991Buf/EiHHeJikoWgHsAIPkBH29+ntdA==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/core": "3.592.0", + "@aws-sdk/middleware-host-header": "3.577.0", + "@aws-sdk/middleware-logger": "3.577.0", + "@aws-sdk/middleware-recursion-detection": "3.577.0", + "@aws-sdk/middleware-user-agent": "3.587.0", + "@aws-sdk/region-config-resolver": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-endpoints": "3.587.0", + "@aws-sdk/util-user-agent-browser": "3.577.0", + "@aws-sdk/util-user-agent-node": "3.587.0", + "@smithy/config-resolver": "^3.0.1", + "@smithy/core": "^2.2.0", + "@smithy/fetch-http-handler": "^3.0.1", + "@smithy/hash-node": "^3.0.0", + "@smithy/invalid-dependency": "^3.0.0", + "@smithy/middleware-content-length": "^3.0.0", + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/middleware-retry": "^3.0.3", + "@smithy/middleware-serde": "^3.0.0", + "@smithy/middleware-stack": "^3.0.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/node-http-handler": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/url-parser": "^3.0.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.3", + "@smithy/util-defaults-mode-node": "^3.0.3", + "@smithy/util-endpoints": "^2.0.1", + "@smithy/util-middleware": "^3.0.0", + "@smithy/util-retry": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-sso-oidc": { + "version": "3.592.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.592.0.tgz", + "integrity": "sha512-11Zvm8nm0s/UF3XCjzFRpQU+8FFVW5rcr3BHfnH6xAe5JEoN6bJN/n+wOfnElnjek+90hh+Qc7s141AMrCjiiw==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.592.0", + "@aws-sdk/core": "3.592.0", + "@aws-sdk/credential-provider-node": "3.592.0", + "@aws-sdk/middleware-host-header": "3.577.0", + "@aws-sdk/middleware-logger": "3.577.0", + "@aws-sdk/middleware-recursion-detection": "3.577.0", + "@aws-sdk/middleware-user-agent": "3.587.0", + "@aws-sdk/region-config-resolver": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-endpoints": "3.587.0", + "@aws-sdk/util-user-agent-browser": "3.577.0", + "@aws-sdk/util-user-agent-node": "3.587.0", + "@smithy/config-resolver": "^3.0.1", + "@smithy/core": "^2.2.0", + "@smithy/fetch-http-handler": "^3.0.1", + "@smithy/hash-node": "^3.0.0", + "@smithy/invalid-dependency": "^3.0.0", + "@smithy/middleware-content-length": "^3.0.0", + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/middleware-retry": "^3.0.3", + "@smithy/middleware-serde": "^3.0.0", + "@smithy/middleware-stack": "^3.0.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/node-http-handler": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/url-parser": "^3.0.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.3", + "@smithy/util-defaults-mode-node": "^3.0.3", + "@smithy/util-endpoints": "^2.0.1", + "@smithy/util-middleware": "^3.0.0", + "@smithy/util-retry": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/client-sts": { + "version": "3.592.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.592.0.tgz", + "integrity": "sha512-KUrOdszZfcrlpKr4dpdkGibZ/qq3Lnfu1rjv1U+V1QJQ9OuMo9J3sDWpWV9tigNqY0aGllarWH5cJbz9868W/w==", + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sso-oidc": "3.592.0", + "@aws-sdk/core": "3.592.0", + "@aws-sdk/credential-provider-node": "3.592.0", + "@aws-sdk/middleware-host-header": "3.577.0", + "@aws-sdk/middleware-logger": "3.577.0", + "@aws-sdk/middleware-recursion-detection": "3.577.0", + "@aws-sdk/middleware-user-agent": "3.587.0", + "@aws-sdk/region-config-resolver": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-endpoints": "3.587.0", + "@aws-sdk/util-user-agent-browser": "3.577.0", + "@aws-sdk/util-user-agent-node": "3.587.0", + "@smithy/config-resolver": "^3.0.1", + "@smithy/core": "^2.2.0", + "@smithy/fetch-http-handler": "^3.0.1", + "@smithy/hash-node": "^3.0.0", + "@smithy/invalid-dependency": "^3.0.0", + "@smithy/middleware-content-length": "^3.0.0", + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/middleware-retry": "^3.0.3", + "@smithy/middleware-serde": "^3.0.0", + "@smithy/middleware-stack": "^3.0.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/node-http-handler": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/url-parser": "^3.0.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-body-length-node": "^3.0.0", + "@smithy/util-defaults-mode-browser": "^3.0.3", + "@smithy/util-defaults-mode-node": "^3.0.3", + "@smithy/util-endpoints": "^2.0.1", + "@smithy/util-middleware": "^3.0.0", + "@smithy/util-retry": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/core": { + "version": "3.592.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.592.0.tgz", + "integrity": "sha512-gLPMXR/HXDP+9gXAt58t7gaMTvRts9i6Q7NMISpkGF54wehskl5WGrbdtHJFylrlJ5BQo3XVY6i661o+EuR1wg==", + "dependencies": { + "@smithy/core": "^2.2.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/signature-v4": "^3.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "fast-xml-parser": "4.2.5", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.587.0.tgz", + "integrity": "sha512-Hyg/5KFECIk2k5o8wnVEiniV86yVkhn5kzITUydmNGCkXdBFHMHRx6hleQ1bqwJHbBskyu8nbYamzcwymmGwmw==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.587.0.tgz", + "integrity": "sha512-Su1SRWVRCuR1e32oxX3C1V4c5hpPN20WYcRfdcr2wXwHqSvys5DrnmuCC+JoEnS/zt3adUJhPliTqpfKgSdMrA==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/fetch-http-handler": "^3.0.1", + "@smithy/node-http-handler": "^3.0.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/util-stream": "^3.0.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.592.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.592.0.tgz", + "integrity": "sha512-3kG6ngCIOPbLJZZ3RV+NsU7HVK6vX1+1DrPJKj9fVlPYn7IXsk8NAaUT5885yC7+jKizjv0cWLrLKvAJV5gfUA==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.587.0", + "@aws-sdk/credential-provider-http": "3.587.0", + "@aws-sdk/credential-provider-process": "3.587.0", + "@aws-sdk/credential-provider-sso": "3.592.0", + "@aws-sdk/credential-provider-web-identity": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@smithy/credential-provider-imds": "^3.1.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/shared-ini-file-loader": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.592.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.592.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.592.0.tgz", + "integrity": "sha512-BguihBGTrEjVBQ07hm+ZsO29eNJaxwBwUZMftgGAm2XcMIEClNPfm5hydxu2BmA4ouIJQJ6nG8pNYghEumM+Aw==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.587.0", + "@aws-sdk/credential-provider-http": "3.587.0", + "@aws-sdk/credential-provider-ini": "3.592.0", + "@aws-sdk/credential-provider-process": "3.587.0", + "@aws-sdk/credential-provider-sso": "3.592.0", + "@aws-sdk/credential-provider-web-identity": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@smithy/credential-provider-imds": "^3.1.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/shared-ini-file-loader": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.587.0.tgz", + "integrity": "sha512-V4xT3iCqkF8uL6QC4gqBJg/2asd/damswP1h9HCfqTllmPWzImS+8WD3VjgTLw5b0KbTy+ZdUhKc0wDnyzkzxg==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/shared-ini-file-loader": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.592.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.592.0.tgz", + "integrity": "sha512-fYFzAdDHKHvhtufPPtrLdSv8lO6GuW3em6n3erM5uFdpGytNpjXvr3XGokIsuXcNkETAY/Xihg+G9ksNE8WJxQ==", + "dependencies": { + "@aws-sdk/client-sso": "3.592.0", + "@aws-sdk/token-providers": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/shared-ini-file-loader": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.587.0.tgz", + "integrity": "sha512-XqIx/I2PG7kyuw3WjAP9wKlxy8IvFJwB8asOFT1xPFoVfZYKIogjG9oLP5YiRtfvDkWIztHmg5MlVv3HdJDGRw==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sts": "^3.587.0" + } + }, + "node_modules/@aws-sdk/middleware-bucket-endpoint": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.587.0.tgz", + "integrity": "sha512-HkFXLPl8pr6BH/Q0JpOESqEKL0ZK3sk7aSZ1S6GE4RXET7H5R94THULXqQFZzD48gZcyFooO/yNKZTqrZFaWKg==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-arn-parser": "3.568.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-config-provider": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-expect-continue": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.577.0.tgz", + "integrity": "sha512-6dPp8Tv4F0of4un5IAyG6q++GrRrNQQ4P2NAMB1W0VO4JoEu1C8GievbbDLi88TFIFmtKpnHB0ODCzwnoe8JsA==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-flexible-checksums": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.587.0.tgz", + "integrity": "sha512-URMwp/budDvKhIvZ4a6zIBfFTun/iDlPWXqsGKYjEtHt8jz27OSjCZtDtIeqW4WTBdKL8KZgQcl+DdaE5M1qiQ==", + "dependencies": { + "@aws-crypto/crc32": "3.0.0", + "@aws-crypto/crc32c": "3.0.0", + "@aws-sdk/types": "3.577.0", + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.577.0.tgz", + "integrity": "sha512-9ca5MJz455CODIVXs0/sWmJm7t3QO4EUa1zf8pE8grLpzf0J94bz/skDWm37Pli13T3WaAQBHCTiH2gUVfCsWg==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-location-constraint": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.577.0.tgz", + "integrity": "sha512-DKPTD2D2s+t2QUo/IXYtVa/6Un8GZ+phSTBkyBNx2kfZz4Kwavhl/JJzSqTV3GfCXkVdFu7CrjoX7BZ6qWeTUA==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.577.0.tgz", + "integrity": "sha512-aPFGpGjTZcJYk+24bg7jT4XdIp42mFXSuPt49lw5KygefLyJM/sB0bKKqPYYivW0rcuZ9brQ58eZUNthrzYAvg==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.577.0.tgz", + "integrity": "sha512-pn3ZVEd2iobKJlR3H+bDilHjgRnNrQ6HMmK9ZzZw89Ckn3Dcbv48xOv4RJvu0aU8SDLl/SNCxppKjeLDTPGBNA==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-ec2": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-ec2/-/middleware-sdk-ec2-3.587.0.tgz", + "integrity": "sha512-mbmgBdw5JVq6zDU54MM6ICSK2ngIkIsQJ/spsy27lXPskQwMuLG5BOYMQf7in5xfMjmnBT9Cxnk/YqaXN1K3+A==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-format-url": "3.577.0", + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/protocol-http": "^4.0.0", + "@smithy/signature-v4": "^3.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.587.0.tgz", + "integrity": "sha512-vtXTGEiw1E9Fax4LmcU2Z208gbrC8ShrdsSLmGcRPpu5NPOGBFBSDG5sy5EDNClrFxIl/Le8coQnD0EDBtx+uQ==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-arn-parser": "3.568.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/signature-v4": "^3.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/util-config-provider": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-signing": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.587.0.tgz", + "integrity": "sha512-tiZaTDj4RvhXGRAlncFn7CSEfL3iNPO67WSaxAq+Ls5j1VgczPhu5262cWONNoMgth3nXR1hhLC4ITSl/a6AzA==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/signature-v4": "^3.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-middleware": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-ssec": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.577.0.tgz", + "integrity": "sha512-i2BPJR+rp8xmRVIGc0h1kDRFcM2J9GnClqqpc+NLSjmYadlcg4mPklisz9HzwFVcRPJ5XcGf3U4BYs5G8+iTyg==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.587.0.tgz", + "integrity": "sha512-SyDomN+IOrygLucziG7/nOHkjUXES5oH5T7p8AboO8oakMQJdnudNXiYWTicQWO52R51U6CR27rcMPTGeMedYA==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@aws-sdk/util-endpoints": "3.587.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/region-config-resolver": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.587.0.tgz", + "integrity": "sha512-93I7IPZtulZQoRK+O20IJ4a1syWwYPzoO2gc3v+/GNZflZPV3QJXuVbIm0pxBsu0n/mzKGUKqSOLPIaN098HcQ==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/types": "^3.0.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.587.0.tgz", + "integrity": "sha512-TR9+ZSjdXvXUz54ayHcCihhcvxI9W7102J1OK6MrLgBlPE7uRhAx42BR9L5lLJ86Xj3LuqPWf//o9d/zR9WVIg==", + "dependencies": { + "@aws-sdk/middleware-sdk-s3": "3.587.0", + "@aws-sdk/types": "3.577.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/signature-v4": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.587.0.tgz", + "integrity": "sha512-ULqhbnLy1hmJNRcukANBWJmum3BbjXnurLPSFXoGdV0llXYlG55SzIla2VYqdveQEEjmsBuTZdFvXAtNpmS5Zg==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/shared-ini-file-loader": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "@aws-sdk/client-sso-oidc": "^3.587.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.577.0.tgz", + "integrity": "sha512-FT2JZES3wBKN/alfmhlo+3ZOq/XJ0C7QOZcDNrpKjB0kqYoKjhVKZ/Hx6ArR0czkKfHzBBEs6y40ebIHx2nSmA==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/util-arn-parser": { + "version": "3.568.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.568.0.tgz", + "integrity": "sha512-XUKJWWo+KOB7fbnPP0+g/o5Ulku/X53t7i/h+sPHr5xxYTJJ9CYnbToo95mzxe7xWvkLrsNtJ8L+MnNn9INs2w==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.587.0.tgz", + "integrity": "sha512-8I1HG6Em8wQWqKcRW6m358mqebRVNpL8XrrEoT4In7xqkKkmYtHRNVYP6lcmiQh5pZ/c/FXu8dSchuFIWyEtqQ==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/types": "^3.0.0", + "@smithy/util-endpoints": "^2.0.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/util-format-url": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.577.0.tgz", + "integrity": "sha512-SyEGC2J+y/krFRuPgiF02FmMYhqbiIkOjDE6k4nYLJQRyS6XEAGxZoG+OHeOVEM+bsDgbxokXZiM3XKGu6qFIg==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/querystring-builder": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.568.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.568.0.tgz", + "integrity": "sha512-3nh4TINkXYr+H41QaPelCceEB2FXP3fxp93YZXB/kqJvX0U9j0N0Uk45gvsjmEPzG8XxkPEeLIfT2I1M7A6Lig==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.577.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.577.0.tgz", + "integrity": "sha512-zEAzHgR6HWpZOH7xFgeJLc6/CzMcx4nxeQolZxVZoB5pPaJd3CjyRhZN0xXeZB0XIRCWmb4yJBgyiugXLNMkLA==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/types": "^3.0.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.587.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.587.0.tgz", + "integrity": "sha512-Pnl+DUe/bvnbEEDHP3iVJrOtE3HbFJBPgsD6vJ+ml/+IYk1Eq49jEG+EHZdNTPz3SDG0kbp2+7u41MKYJHR/iQ==", + "dependencies": { + "@aws-sdk/types": "3.577.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.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-sdk/xml-builder": { + "version": "3.575.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.575.0.tgz", + "integrity": "sha512-cWgAwmbFYNCFzPwxL705+lWps0F3ZvOckufd2KKoEZUmtpVw9/txUXNrPySUXSmRTSRhoatIMABNfStWR043bQ==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-p6GlFGBt9K4MYLu72YuJ523NVR4A8oHlC5M2JO6OmQqN8kAc/uh1JqLE+FizTokrSJGg0CSvC+BrsmGzKtsZKA==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/chunked-blob-reader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-3.0.0.tgz", + "integrity": "sha512-sbnURCwjF0gSToGlsBiAmd1lRCmSn72nu9axfJu5lIx6RUEgHu6GwTMbqCdhQSi0Pumcm5vFxsi9XWXb2mTaoA==", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/chunked-blob-reader-native": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-3.0.0.tgz", + "integrity": "sha512-VDkpCYW+peSuM4zJip5WDfqvg2Mo/e8yxOv3VF1m11y7B8KKMKVFtmZWDe36Fvk8rGuWrPZHHXZ7rR7uM5yWyg==", + "dependencies": { + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/config-resolver": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.1.tgz", + "integrity": "sha512-hbkYJc20SBDz2qqLzttjI/EqXemtmWk0ooRznLsiXp3066KQRTvuKHa7U4jCZCJq6Dozqvy0R1/vNESC9inPJg==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.0", + "@smithy/types": "^3.0.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/core": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.2.0.tgz", + "integrity": "sha512-ygLZSSKgt9bR8HAxR9mK+U5obvAJBr6zlQuhN5soYWx/amjDoQN4dTkydTypgKe6rIbUjTILyLU+W5XFwXr4kg==", + "dependencies": { + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/middleware-retry": "^3.0.3", + "@smithy/middleware-serde": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/util-middleware": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.1.0.tgz", + "integrity": "sha512-q4A4d38v8pYYmseu/jTS3Z5I3zXlEOe5Obi+EJreVKgSVyWUHOd7/yaVCinC60QG4MRyCs98tcxBH1IMC0bu7Q==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/types": "^3.0.0", + "@smithy/url-parser": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-codec": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-3.0.0.tgz", + "integrity": "sha512-PUtyEA0Oik50SaEFCZ0WPVtF9tz/teze2fDptW6WRXl+RrEenH8UbEjudOz8iakiMl3lE3lCVqYf2Y+znL8QFQ==", + "dependencies": { + "@aws-crypto/crc32": "3.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/eventstream-serde-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.0.tgz", + "integrity": "sha512-NB7AFiPN4NxP/YCAnrvYR18z2/ZsiHiF7VtG30gshO9GbFrIb1rC8ep4NGpJSWrz6P64uhPXeo4M0UsCLnZKqw==", + "dependencies": { + "@smithy/eventstream-serde-universal": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-config-resolver": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.0.tgz", + "integrity": "sha512-RUQG3vQ3LX7peqqHAbmayhgrF5aTilPnazinaSGF1P0+tgM3vvIRWPHmlLIz2qFqB9LqFIxditxc8O2Z6psrRw==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.0.tgz", + "integrity": "sha512-baRPdMBDMBExZXIUAoPGm/hntixjt/VFpU6+VmCyiYJYzRHRxoaI1MN+5XE+hIS8AJ2GCHLMFEIOLzq9xx1EgQ==", + "dependencies": { + "@smithy/eventstream-serde-universal": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/eventstream-serde-universal": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.0.tgz", + "integrity": "sha512-HNFfShmotWGeAoW4ujP8meV9BZavcpmerDbPIjkJbxKbN8RsUcpRQ/2OyIxWNxXNH2GWCAxuSB7ynmIGJlQ3Dw==", + "dependencies": { + "@smithy/eventstream-codec": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.0.1.tgz", + "integrity": "sha512-uaH74i5BDj+rBwoQaXioKpI0SHBJFtOVwzrCpxZxphOW0ki5jhj7dXvDMYM2IJem8TpdFvS2iC08sjOblfFGFg==", + "dependencies": { + "@smithy/protocol-http": "^4.0.0", + "@smithy/querystring-builder": "^3.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/hash-blob-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-3.0.0.tgz", + "integrity": "sha512-/Wbpdg+bwJvW7lxR/zpWAc1/x/YkcqguuF2bAzkJrvXriZu1vm8r+PUdE4syiVwQg7PPR2dXpi3CLBb9qRDaVQ==", + "dependencies": { + "@smithy/chunked-blob-reader": "^3.0.0", + "@smithy/chunked-blob-reader-native": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/hash-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.0.tgz", + "integrity": "sha512-84qXstNemP3XS5jcof0el6+bDfjzuvhJPQTEfro3lgtbCtKgzPm3MgiS6ehXVPjeQ5+JS0HqmTz8f/RYfzHVxw==", + "dependencies": { + "@smithy/types": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/hash-stream-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-3.0.0.tgz", + "integrity": "sha512-J0i7de+EgXDEGITD4fxzmMX8CyCNETTIRXlxjMiNUvvu76Xn3GJ31wQR85ynlPk2wI1lqoknAFJaD1fiNDlbIA==", + "dependencies": { + "@smithy/types": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/invalid-dependency": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.0.tgz", + "integrity": "sha512-F6wBBaEFgJzj0s4KUlliIGPmqXemwP6EavgvDqYwCH40O5Xr2iMHvS8todmGVZtuJCorBkXsYLyTu4PuizVq5g==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/md5-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-3.0.0.tgz", + "integrity": "sha512-Tm0vrrVzjlD+6RCQTx7D3Ls58S3FUH1ZCtU1MIh/qQmaOo1H9lMN2as6CikcEwgattnA9SURSdoJJ27xMcEfMA==", + "dependencies": { + "@smithy/types": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/middleware-content-length": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.0.tgz", + "integrity": "sha512-3C4s4d/iGobgCtk2tnWW6+zSTOBg1PRAm2vtWZLdriwTroFbbWNSr3lcyzHdrQHnEXYCC5K52EbpfodaIUY8sg==", + "dependencies": { + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.0.1.tgz", + "integrity": "sha512-lQ/UOdGD4KM5kLZiAl0q8Qy3dPbynvAXKAdXnYlrA1OpaUwr+neSsVokDZpY6ZVb5Yx8jnus29uv6XWpM9P4SQ==", + "dependencies": { + "@smithy/middleware-serde": "^3.0.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/shared-ini-file-loader": "^3.1.0", + "@smithy/types": "^3.0.0", + "@smithy/url-parser": "^3.0.0", + "@smithy/util-middleware": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/middleware-retry": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.3.tgz", + "integrity": "sha512-Wve1qzJb83VEU/6q+/I0cQdAkDnuzELC6IvIBwDzUEiGpKqXgX1v10FUuZGbRS6Ov/P+HHthcAoHOJZQvZNAkA==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/service-error-classification": "^3.0.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "@smithy/util-middleware": "^3.0.0", + "@smithy/util-retry": "^3.0.0", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/middleware-serde": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.0.tgz", + "integrity": "sha512-I1vKG1foI+oPgG9r7IMY1S+xBnmAn1ISqployvqkwHoSb8VPsngHDTOgYGYBonuOKndaWRUGJZrKYYLB+Ane6w==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/middleware-stack": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.0.tgz", + "integrity": "sha512-+H0jmyfAyHRFXm6wunskuNAqtj7yfmwFB6Fp37enytp2q047/Od9xetEaUbluyImOlGnGpaVGaVfjwawSr+i6Q==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/node-config-provider": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.0.tgz", + "integrity": "sha512-ngfB8QItUfTFTfHMvKuc2g1W60V1urIgZHqD1JNFZC2tTWXahqf2XvKXqcBS7yZqR7GqkQQZy11y/lNOUWzq7Q==", + "dependencies": { + "@smithy/property-provider": "^3.1.0", + "@smithy/shared-ini-file-loader": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/node-http-handler": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.0.0.tgz", + "integrity": "sha512-3trD4r7NOMygwLbUJo4eodyQuypAWr7uvPnebNJ9a70dQhVn+US8j/lCnvoJS6BXfZeF7PkkkI0DemVJw+n+eQ==", + "dependencies": { + "@smithy/abort-controller": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/querystring-builder": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/property-provider": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.0.tgz", + "integrity": "sha512-Tj3+oVhqdZgemjCiWjFlADfhvLF4C/uKDuKo7/tlEsRQ9+3emCreR2xndj970QSRSsiCEU8hZW3/8JQu+n5w4Q==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/protocol-http": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.0.0.tgz", + "integrity": "sha512-qOQZOEI2XLWRWBO9AgIYuHuqjZ2csyr8/IlgFDHDNuIgLAMRx2Bl8ck5U5D6Vh9DPdoaVpuzwWMa0xcdL4O/AQ==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/querystring-builder": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.0.tgz", + "integrity": "sha512-bW8Fi0NzyfkE0TmQphDXr1AmBDbK01cA4C1Z7ggwMAU5RDz5AAv/KmoRwzQAS0kxXNf/D2ALTEgwK0U2c4LtRg==", + "dependencies": { + "@smithy/types": "^3.0.0", + "@smithy/util-uri-escape": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/querystring-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.0.tgz", + "integrity": "sha512-UzHwthk0UEccV4dHzPySnBy34AWw3V9lIqUTxmozQ+wPDAO9csCWMfOLe7V9A2agNYy7xE+Pb0S6K/J23JSzfQ==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/service-error-classification": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.0.tgz", + "integrity": "sha512-3BsBtOUt2Gsnc3X23ew+r2M71WwtpHfEDGhHYHSDg6q1t8FrWh15jT25DLajFV1H+PpxAJ6gqe9yYeRUsmSdFA==", + "dependencies": { + "@smithy/types": "^3.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.0.tgz", + "integrity": "sha512-dAM7wSX0NR3qTNyGVN/nwwpEDzfV9T/3AN2eABExWmda5VqZKSsjlINqomO5hjQWGv+IIkoXfs3u2vGSNz8+Rg==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/signature-v4": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-3.0.0.tgz", + "integrity": "sha512-kXFOkNX+BQHe2qnLxpMEaCRGap9J6tUGLzc3A9jdn+nD4JdMwCKTJ+zFwQ20GkY+mAXGatyTw3HcoUlR39HwmA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-middleware": "^3.0.0", + "@smithy/util-uri-escape": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/smithy-client": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.1.1.tgz", + "integrity": "sha512-tj4Ku7MpzZR8cmVuPcSbrLFVxmptWktmJMwST/uIEq4sarabEdF8CbmQdYB7uJ/X51Qq2EYwnRsoS7hdR4B7rA==", + "dependencies": { + "@smithy/middleware-endpoint": "^3.0.1", + "@smithy/middleware-stack": "^3.0.0", + "@smithy/protocol-http": "^4.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-stream": "^3.0.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.0.0.tgz", + "integrity": "sha512-VvWuQk2RKFuOr98gFhjca7fkBS+xLLURT8bUjk5XQoV0ZLm7WPwWPPY3/AwzTLuUBDeoKDCthfe1AsTUWaSEhw==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/url-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.0.tgz", + "integrity": "sha512-2XLazFgUu+YOGHtWihB3FSLAfCUajVfNBXGGYjOaVKjLAuAxx3pSBY3hBgLzIgB17haf59gOG3imKqTy8mcrjw==", + "dependencies": { + "@smithy/querystring-parser": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/util-base64": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", + "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-body-length-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", + "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", + "dependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@smithy/util-body-length-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz", + "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "dependencies": { + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-config-provider": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", + "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.3.tgz", + "integrity": "sha512-3DFON2bvXJAukJe+qFgPV/rorG7ZD3m4gjCXHD1V5z/tgKQp5MCTCLntrd686tX6tj8Uli3lefWXJudNg5WmCA==", + "dependencies": { + "@smithy/property-provider": "^3.1.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-node": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.3.tgz", + "integrity": "sha512-D0b8GJXecT00baoSQ3Iieu3k3mZ7GY8w1zmg8pdogYrGvWJeLcIclqk2gbkG4K0DaBGWrO6v6r20iwIFfDYrmA==", + "dependencies": { + "@smithy/config-resolver": "^3.0.1", + "@smithy/credential-provider-imds": "^3.1.0", + "@smithy/node-config-provider": "^3.1.0", + "@smithy/property-provider": "^3.1.0", + "@smithy/smithy-client": "^3.1.1", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-endpoints": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.0.1.tgz", + "integrity": "sha512-ZRT0VCOnKlVohfoABMc8lWeQo/JEFuPWctfNRXgTHbyOVssMOLYFUNWukxxiHRGVAhV+n3c0kPW+zUqckjVPEA==", + "dependencies": { + "@smithy/node-config-provider": "^3.1.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-hex-encoding": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", + "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-middleware": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.0.tgz", + "integrity": "sha512-q5ITdOnV2pXHSVDnKWrwgSNTDBAMHLptFE07ua/5Ty5WJ11bvr0vk2a7agu7qRhrCFRQlno5u3CneU5EELK+DQ==", + "dependencies": { + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-retry": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.0.tgz", + "integrity": "sha512-nK99bvJiziGv/UOKJlDvFF45F00WgPLKVIGUfAK+mDhzVN2hb/S33uW2Tlhg5PVBoqY7tDVqL0zmu4OxAHgo9g==", + "dependencies": { + "@smithy/service-error-classification": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-stream": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.0.1.tgz", + "integrity": "sha512-7F7VNNhAsfMRA8I986YdOY5fE0/T1/ZjFF6OLsqkvQVNP3vZ/szYDfGCyphb7ioA09r32K/0qbSFfNFU68aSzA==", + "dependencies": { + "@smithy/fetch-http-handler": "^3.0.1", + "@smithy/node-http-handler": "^3.0.0", + "@smithy/types": "^3.0.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-uri-escape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", + "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "dependencies": { + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-waiter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-3.0.0.tgz", + "integrity": "sha512-+fEXJxGDLCoqRKVSmo0auGxaqbiCo+8oph+4auefYjaNxjOLKSY2MxVQfRzo65PaZv4fr+5lWg+au7vSuJJ/zw==", + "dependencies": { + "@smithy/abort-controller": "^3.0.0", + "@smithy/types": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "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==", + "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==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "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/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==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "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==", + "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==" + }, + "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==" + }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "engines": { + "node": ">=6" + } + }, + "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/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==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/prettier": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.1.tgz", + "integrity": "sha512-7CAwy5dRsxs8PHXT3twixW9/OEll8MLE0VRPCJyl7CkS6VHGPSlsVaWTiASPTyGyYRyApxlaWTzwUxVNrhcwDg==", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" + }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "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==", + "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/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "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==", + "engines": { + "node": ">=12" + } + } + } +} diff --git a/setup/package.json b/setup/package.json new file mode 100644 index 0000000..611d943 --- /dev/null +++ b/setup/package.json @@ -0,0 +1,22 @@ +{ + "name": "fargate-setup", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node index.js" + }, + "author": "Gabriel Kaźmierczak", + "license": "ISC", + "type": "module", + "dependencies": { + "@aws-sdk/client-ec2": "^3.592.0", + "@aws-sdk/client-ecs": "^3.592.0", + "@aws-sdk/client-efs": "^3.592.0", + "@aws-sdk/client-lambda": "^3.592.0", + "@aws-sdk/client-s3": "^3.592.0", + "prettier": "^3.3.1", + "yargs": "^17.7.2" + } +} diff --git a/setup/runTask.js b/setup/runTask.js new file mode 100644 index 0000000..be9338a --- /dev/null +++ b/setup/runTask.js @@ -0,0 +1,54 @@ +import { ECSClient } from "@aws-sdk/client-ecs"; +import { RunTaskCommand, DescribeTasksCommand } from "@aws-sdk/client-ecs"; +import { hideBin } from "yargs/helpers"; +import yargs from "yargs"; + +const argv = yargs(hideBin(process.argv)) + .option("cluster", { + alias: "c", + description: "cluster ARN", + type: "string", + demandOption: false, + }) + .option("task", { + alias: "t", + description: "task ARN", + type: "string", + demandOption: false, + }) + .option("subnet", { + alias: "s", + description: "subnet id", + type: "string", + demandOption: false, + }) + .help() + .alias("help", "h").argv; + +export async function main(args) { + const ecsClient = new ECSClient({ region: "us-east-1" }); + + try { + const params = { + cluster: args.cluster, + launchType: "FARGATE", + taskDefinition: args.task, + count: 1, + networkConfiguration: { + awsvpcConfiguration: { + subnets: [args.subnet], + securityGroups: [], + assignPublicIp: "ENABLED", + }, + }, + }; + + const command = new RunTaskCommand(params); + const response = await ecsClient.send(command); + console.log(response); + } catch (err) { + console.error("Error executing ECS Fargate task:", err); + } +} + +main(argv); diff --git a/setup/vpcUtils.js b/setup/vpcUtils.js new file mode 100644 index 0000000..c0a6a0c --- /dev/null +++ b/setup/vpcUtils.js @@ -0,0 +1,190 @@ +import { + CreateVpcCommand, + CreateSubnetCommand, + DescribeSecurityGroupsCommand, + CreateInternetGatewayCommand, + AttachInternetGatewayCommand, + CreateRouteTableCommand, + CreateRouteCommand, + AssociateRouteTableCommand, + ModifyVpcAttributeCommand, + AuthorizeSecurityGroupIngressCommand, +} from "@aws-sdk/client-ec2"; + +export async function createVPCAndSubnets(ec2Client) { + try { + const createVpcParams = { + CidrBlock: "10.0.0.0/16", + TagSpecifications: [ + { + ResourceType: "vpc", + Tags: [{ Key: "Name", Value: "HyperflowFargateVPC" }], + }, + ], + }; + + const vpcData = await ec2Client.send( + new CreateVpcCommand(createVpcParams), + ); + const vpcId = vpcData.Vpc.VpcId; + console.log("VPC created successfully:", vpcData.Vpc); + + const dnsParams = { + VpcId: vpcId, + EnableDnsHostnames: { + Value: true, + }, + }; + await ec2Client.send(new ModifyVpcAttributeCommand(dnsParams)); + console.log("DNS hostnames enabled for VPC:", vpcId); + + const createSubnetParams1 = { + VpcId: vpcId, + CidrBlock: "10.0.1.0/24", + AvailabilityZone: "us-east-1a", + TagSpecifications: [ + { + ResourceType: "subnet", + Tags: [{ Key: "Name", Value: "HyperflowSubnet1" }], + }, + ], + }; + + const subnetData1 = await ec2Client.send( + new CreateSubnetCommand(createSubnetParams1), + ); + console.log("Subnet 1 created successfully:", subnetData1.Subnet); + + const createSubnetParams2 = { + VpcId: vpcId, + CidrBlock: "10.0.2.0/24", + AvailabilityZone: "us-east-1b", + TagSpecifications: [ + { + ResourceType: "subnet", + Tags: [{ Key: "Name", Value: "HyperflowSubnet2" }], + }, + ], + }; + + const subnetData2 = await ec2Client.send( + new CreateSubnetCommand(createSubnetParams2), + ); + + console.log("Subnet 2 created successfully:", subnetData2.Subnet); + const securityGroup = await getDefaultSecurityGroup(ec2Client, vpcId); + + const ingressRuleParams = { + GroupId: securityGroup.GroupId, + IpPermissions: [ + { + IpProtocol: "tcp", + FromPort: 2049, + ToPort: 2049, + IpRanges: [{ CidrIp: "0.0.0.0/0" }], + }, + ], + }; + + const data = await ec2Client.send( + new AuthorizeSecurityGroupIngressCommand(ingressRuleParams), + ); + console.log("Security Group Ingress Rule added successfully", data); + + const igwData = await ec2Client.send( + new CreateInternetGatewayCommand({}), + ); + const igwId = igwData.InternetGateway.InternetGatewayId; + console.log("Internet Gateway created successfully:", igwId); + + const attachIgwParams = { + InternetGatewayId: igwId, + VpcId: vpcId, + }; + await ec2Client.send(new AttachInternetGatewayCommand(attachIgwParams)); + console.log("Internet Gateway attached successfully to VPC:", vpcId); + + const routeTableParams = { + VpcId: vpcId, + }; + const routeTableData = await ec2Client.send( + new CreateRouteTableCommand(routeTableParams), + ); + const routeTableId = routeTableData.RouteTable.RouteTableId; + console.log("Route Table created successfully:", routeTableId); + + const routeParams = { + RouteTableId: routeTableId, + DestinationCidrBlock: "0.0.0.0/0", + GatewayId: igwId, + }; + await ec2Client.send(new CreateRouteCommand(routeParams)); + console.log("Route to Internet Gateway created successfully."); + + const associateRouteTableParams1 = { + SubnetId: subnetData1.Subnet.SubnetId, + RouteTableId: routeTableId, + }; + await ec2Client.send( + new AssociateRouteTableCommand(associateRouteTableParams1), + ); + console.log( + "Route Table associated successfully with Subnet 1:", + subnetData1.Subnet.SubnetId, + ); + + const associateRouteTableParams2 = { + SubnetId: subnetData2.Subnet.SubnetId, + RouteTableId: routeTableId, + }; + await ec2Client.send( + new AssociateRouteTableCommand(associateRouteTableParams2), + ); + console.log( + "Route Table associated successfully with Subnet 2:", + subnetData2.Subnet.SubnetId, + ); + + return { + securityGroup, + subnets: [subnetData1.Subnet, subnetData2.Subnet], + }; + } catch (err) { + console.error("Error creating VPC or subnets:", err); + return []; + } +} + +async function getDefaultSecurityGroup(ec2Client, vpcId) { + try { + const params = { + Filters: [ + { + Name: "vpc-id", + Values: [vpcId], + }, + { + Name: "group-name", + Values: ["default"], + }, + ], + }; + + const data = await ec2Client.send( + new DescribeSecurityGroupsCommand(params), + ); + + if (data.SecurityGroups && data.SecurityGroups.length > 0) { + const defaultSecurityGroup = data.SecurityGroups[0]; + console.log( + "Default security group for VPC:", + defaultSecurityGroup, + ); + return defaultSecurityGroup; + } else { + console.log("No default security group found for VPC:", vpcId); + } + } catch (err) { + console.error("Error retrieving the default security group:", err); + } +} diff --git a/software/Montage.tar.gz b/software/Montage.tar.gz new file mode 100644 index 0000000..6bf781a Binary files /dev/null and b/software/Montage.tar.gz differ diff --git a/software/libnethogs.so.0.8.5-63-g68033bf b/software/libnethogs.so.0.8.5-63-g68033bf new file mode 100755 index 0000000..1ad6584 Binary files /dev/null and b/software/libnethogs.so.0.8.5-63-g68033bf differ diff --git a/software/nethogs-wrapper.py b/software/nethogs-wrapper.py new file mode 100644 index 0000000..34ca5ae --- /dev/null +++ b/software/nethogs-wrapper.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python3 +import ctypes +import signal +import datetime +import threading + +# This is a Python 3 demo of how to interact with the Nethogs library via Python. The Nethogs +# library operates via a callback. The callback implemented here just formats the data it receives +# and prints it to stdout. This must be run as root (`sudo python3 python-wrapper.py`). +# By Philip Semanchuk (psemanchuk@caktusgroup.com) November 2016 +# Copyright waived; released into public domain as is. + +# The code is multi-threaded to allow it to respond to SIGTERM and SIGINT (Ctrl+C). In single- +# threaded mode, while waiting in the Nethogs monitor loop, this Python code won't receive Ctrl+C +# until network activity occurs and the callback is executed. By using 2 threads, we can have the +# main thread listen for SIGINT while the secondary thread is blocked in the monitor loop. + +####################### +# BEGIN CONFIGURATION # +####################### + +# You can use this to monitor only certain devices, like: +# device_names = ['enp4s0', 'docker0'] +device_names = [] + +# LIBRARY_NAME has to be exact, although it doesn't need to include the full path. +# The version tagged as 0.8.5 (download link below) builds a library with this name. +# https://github.com/raboof/nethogs/archive/v0.8.5.tar.gz +# LIBRARY_NAME = 'libnethogs.so.0.8.5' +LIBRARY_NAME = 'libnethogs.so.0.8.5-63-g68033bf' + +# EXPERIMENTAL: Optionally, specify a capture filter in pcap format (same as +# used by tcpdump(1)) or None. See `man pcap-filter` for full information. +# Note that this feature is EXPERIMENTAL (in libnethogs) and may be removed or +# changed in an incompatible way in a future release. +# example: +# FILTER = 'port 80 or port 8080 or port 443' +FILTER = None + +##################### +# END CONFIGURATION # +##################### + +# Here are some definitions from libnethogs.h +# https://github.com/raboof/nethogs/blob/master/src/libnethogs.h +# Possible actions are NETHOGS_APP_ACTION_SET & NETHOGS_APP_ACTION_REMOVE +# Action REMOVE is sent when nethogs decides a connection or a process has died. There are two +# timeouts defined, PROCESSTIMEOUT (150 seconds) and CONNTIMEOUT (50 seconds). AFAICT, the latter +# trumps the former so we see a REMOVE action after ~45-50 seconds of inactivity. +class Action(): + SET = 1 + REMOVE = 2 + + MAP = {SET: 'SET', REMOVE: 'REMOVE'} + +class LoopStatus(): + """Return codes from nethogsmonitor_loop()""" + OK = 0 + FAILURE = 1 + NO_DEVICE = 2 + + MAP = {OK: 'OK', FAILURE: 'FAILURE', NO_DEVICE: 'NO_DEVICE'} + +# The sent/received KB/sec values are averaged over 5 seconds; see PERIOD in nethogs.h. +# https://github.com/raboof/nethogs/blob/master/src/nethogs.h#L43 +# sent_bytes and recv_bytes are a running total +class NethogsMonitorRecord(ctypes.Structure): + """ctypes version of the struct of the same name from libnethogs.h""" + _fields_ = (('record_id', ctypes.c_int), + ('name', ctypes.c_char_p), + ('pid', ctypes.c_int), + ('uid', ctypes.c_uint32), + ('device_name', ctypes.c_char_p), + ('sent_bytes', ctypes.c_uint64), + ('recv_bytes', ctypes.c_uint64), + ('sent_kbs', ctypes.c_float), + ('recv_kbs', ctypes.c_float), + ) + + +def signal_handler(signal, frame): + print('SIGINT received; requesting exit from monitor loop.') + lib.nethogsmonitor_breakloop() + + +def dev_args(devnames): + """ + Return the appropriate ctypes arguments for a device name list, to pass + to libnethogs ``nethogsmonitor_loop_devices``. The return value is a + 2-tuple of devc (``ctypes.c_int``) and devicenames (``ctypes.POINTER``) + to an array of ``ctypes.c_char``). + + :param devnames: list of device names to monitor + :type devnames: list + :return: 2-tuple of devc, devicenames ctypes arguments + :rtype: tuple + """ + devc = len(devnames) + devnames_type = ctypes.c_char_p * devc + devnames_arg = devnames_type() + for idx, val in enumerate(devnames): + devnames_arg[idx] = (val + chr(0)).encode('ascii') + return ctypes.c_int(devc), ctypes.cast( + devnames_arg, ctypes.POINTER(ctypes.c_char_p) + ) + + +def run_monitor_loop(lib, devnames): + # Create a type for my callback func. The callback func returns void (None), and accepts as + # params an int and a pointer to a NethogsMonitorRecord instance. + # The params and return type of the callback function are mandated by nethogsmonitor_loop(). + # See libnethogs.h. + CALLBACK_FUNC_TYPE = ctypes.CFUNCTYPE( + ctypes.c_void_p, ctypes.c_int, ctypes.POINTER(NethogsMonitorRecord) + ) + + filter_arg = FILTER + if filter_arg is not None: + filter_arg = ctypes.c_char_p(filter_arg.encode('ascii')) + + if len(devnames) < 1: + # monitor all devices + rc = lib.nethogsmonitor_loop( + CALLBACK_FUNC_TYPE(network_activity_callback), + filter_arg + ) + else: + devc, devicenames = dev_args(devnames) + rc = lib.nethogsmonitor_loop_devices( + CALLBACK_FUNC_TYPE(network_activity_callback), + filter_arg, + devc, + devicenames, + ctypes.c_bool(False) + ) + + if rc != LoopStatus.OK: + print('nethogsmonitor_loop returned {}'.format(LoopStatus.MAP[rc])) + else: + print('exiting monitor loop') + + +def network_activity_callback(action, data): + print(datetime.datetime.now().strftime('@%H:%M:%S.%f')) + + # Action type is either SET or REMOVE. I have never seen nethogs send an unknown action + # type, and I don't expect it to do so. + action_type = Action.MAP.get(action, 'Unknown') + + print('Action: {}'.format(action_type)) + print('Record id: {}'.format(data.contents.record_id)) + print('Name: {}'.format(data.contents.name)) + print('PID: {}'.format(data.contents.pid)) + print('UID: {}'.format(data.contents.uid)) + print('Device name: {}'.format(data.contents.device_name.decode('ascii'))) + print('Sent/Recv bytes: {} / {}'.format(data.contents.sent_bytes, data.contents.recv_bytes)) + print('Sent/Recv kbs: {} / {}'.format(data.contents.sent_kbs, data.contents.recv_kbs)) + print('-' * 30) + +############# Main begins here ############## + +signal.signal(signal.SIGINT, signal_handler) +signal.signal(signal.SIGTERM, signal_handler) + +lib = ctypes.CDLL(LIBRARY_NAME) + +monitor_thread = threading.Thread( + target=run_monitor_loop, args=(lib, device_names,) +) + +monitor_thread.start() + +done = False +while not done: + monitor_thread.join(0.3) + done = not monitor_thread.is_alive()